package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddGetDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataAddGetVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.parse.data.FormDataUpdateGetAnalysisDataHelp;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductListDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.customer.pojo.dto.ChangeStatusDTO;
import com.xbongbong.pro.detailtab.pojo.OneKeyProduceProductPojo;
import com.xbongbong.pro.detailtab.vo.ProductSummaryVO;
import com.xbongbong.pro.domain.entity.LinkProductRelyEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataValueEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BomErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductionOrderErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.UserTeamErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WarehouseErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.EsDataDTO;
import com.xbongbong.pro.formdata.pojo.AfterSavePojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockListDTO;
import com.xbongbong.pro.instock.pojo.dto.RetMaterielListDTO;
import com.xbongbong.pro.instock.pojo.vo.InstockListVO;
import com.xbongbong.pro.instock.pojo.vo.RetMaterielListVO;
import com.xbongbong.pro.instockproduct.pojo.vo.InstockProductDeleteBatchVO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.outstockproduct.pojo.dto.OutstockProductListDTO;
import com.xbongbong.pro.outstockproduct.pojo.vo.OutstockProductListVO;
import com.xbongbong.pro.product.pojo.ProductSavePojo;
import com.xbongbong.pro.product.pojo.dto.MaterielDTO;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.vo.DetailProductVO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderDeleteBatchDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderEditAttrUpdateDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderListDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderUpdateBatchDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderUpdateByBusinessRuleDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderUpdateDTO;
import com.xbongbong.pro.productionorder.pojo.vo.ProductionOrderDeleteBatchVO;
import com.xbongbong.pro.productionorder.pojo.vo.ProductionOrderListVO;
import com.xbongbong.pro.productionorder.pojo.vo.ProductionOrderUpdateBatchVO;
import com.xbongbong.pro.productionorderproduct.pojo.dto.FormatProductionOrderProductDTO;
import com.xbongbong.pro.productionorderproduct.pojo.dto.ProductionOrderProductDeleteBatchDTO;
import com.xbongbong.pro.productionorderuser.pojo.dto.ProductionOrderUserDeleteBatchDTO;
import com.xbongbong.pro.simulationproduce.pojo.dto.ProductionOrderAddGetDTO;
import com.xbongbong.pro.warehouse.pojo.dto.ProductWarehouseMapDTO;
import com.xbongbong.pro.warehouse.pojo.dto.WarehouseDTO;
import com.xbongbong.pro.warehouse.pojo.vo.ProductWarehouseMapVO;
import com.xbongbong.saas.analytical.impl.ProductionOrderValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BomProductEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.ProductionOrderProductEntity;
import com.xbongbong.saas.domain.entity.ProductionOrderUserEntity;
import com.xbongbong.saas.domain.entity.ext.BomBillEntityExt;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductionOrderEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductionOrderProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.enums.BusinessProductEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperatePageEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.UpdateDataTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.BomBillEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.WarehouseEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.product.BomMaterielProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderFinishProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderMaterielProductEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.help.FieldAttrHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasGetHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.ShowFormatHelp;
import com.xbongbong.saas.help.workflow.ProductionOrderHelp;
import com.xbongbong.saas.model.BomBillModel;
import com.xbongbong.saas.model.BomProductModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.LinkProductRelyModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.ProductionOrderModel;
import com.xbongbong.saas.model.ProductionOrderProductModel;
import com.xbongbong.saas.model.ProductionOrderUserModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.service.BomBillService;
import com.xbongbong.saas.service.BusinessProductService;
import com.xbongbong.saas.service.InstockService;
import com.xbongbong.saas.service.OutstockProductService;
import com.xbongbong.saas.service.OutstockService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.ProductionOrderProductService;
import com.xbongbong.saas.service.ProductionOrderService;
import com.xbongbong.saas.service.ProductionOrderUserService;
import com.xbongbong.saas.service.SaasDetailTabService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.WarehouseService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.ProductHelp;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static com.xbongbong.saas.enums.RelativeProductEnum.ATTRITION_RATE;
import static com.xbongbong.saas.enums.RelativeProductEnum.BARCODE;
import static com.xbongbong.saas.enums.RelativeProductEnum.NAME;
import static com.xbongbong.saas.enums.RelativeProductEnum.NUM;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCT_NO;
import static com.xbongbong.saas.enums.RelativeProductEnum.SPECIFICATION;
import static com.xbongbong.saas.enums.RelativeProductEnum.STOCK;
import static com.xbongbong.saas.enums.RelativeProductEnum.THUMBNAIL;
import static com.xbongbong.saas.enums.RelativeProductEnum.UNIT;
import static com.xbongbong.saas.enums.RelativeProductEnum.UNIT_NUM;
import static com.xbongbong.saas.enums.RelativeProductEnum.WAREHOUSE;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 生产单业务实现
 *
 * @author feng.zheng
 * @version v1.0
 * @date 2019/1/22 15:11
 * @since v1.0
 */
@Service("productionOrderService")
public class ProductionOrderServiceImpl implements ProductionOrderService {

    private static final Logger LOG = LoggerFactory.getLogger(ProductionOrderServiceImpl.class);

    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ShowFormatHelp showFormatHelp;
    @Resource
    private ProductionOrderModel productionOrderModel;
    @Resource
    private ProductionOrderProductModel productionOrderProductModel;
    @Resource
    private ProductionOrderUserModel productionOrderUserModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private InstockService instockService;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private OutstockProductService outstockProductService;
    @Resource
    private ProductionOrderUserService productionOrderUserService;
    @Resource
    private ProductionOrderProductService productionOrderProductService;
    @Resource
    private FieldAttrHelp fieldAttrHelp;
    @Resource
    private OutstockService outstockService;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private BusinessProductService businessProductService;
    @Resource
    private SaasDetailTabService saasDetailTabService;
    @Resource
    private BomProductModel bomProductModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private BomBillModel bomBillModel;
    @Resource
    private ProductService productService;
    @Resource
    private ProductHelp productHelp;
    @Resource
    private SaasGetHelp saasGetHelp;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private EsHelper esHelper;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private BomBillService bomBillService;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private LinkProductRelyModel linkProductRelyModel;
    @Resource
    private UserHelp userHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private FormDataUpdateGetAnalysisDataHelp formDataUpdateGetAnalysisDataHelp;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private ProductionOrderValidateAnalyticalServiceImpl productionOrderAnalyticalService;
    @Resource
    private ProductionOrderHelp productionOrderHelp;
    @Resource
    private TeamDataHelp teamDataHelp;
    @Resource
    private UserTeamHelp userTeamHelp;

    /**
     * 生产单保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @throws XbbException 业务异常
     * @author feng.zheng
     * @date 2019/1/18
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        productionOrderAnalyticalService.beforeSave(validateDataDTO);
    }

    @Override
    public PagingProductVO getPagingProduct(PagingProductDTO pagingProductDTO) throws XbbException {
        PagingProductVO pagingProductVO = new PagingProductVO();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, pagingProductDTO.getCorpid());
        modelMap.put(ParameterConstant.PRODUCTION_ORDER_ID, pagingProductDTO.getDataId());
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE,  pagingProductDTO.getPage());
        modelMap.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        if (Objects.equals(pagingProductDTO.getAttr(), ProductionOrderEnum.PRODUCT.getAttr())) {
            modelMap.put(ParameterConstant.TYPE, 1);
        }else if (Objects.equals(pagingProductDTO.getAttr(), ProductionOrderEnum.MATERIEL.getAttr())) {
            modelMap.put(ParameterConstant.TYPE, 2);
        }
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, productionOrderProductModel, pagingProductDTO.getPageSize());
        List<ProductionOrderProductEntity> productionOrderProductEntityList = (List<ProductionOrderProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, productionOrderProductModel);
        if (pagingProductDTO.getUpdateDataTypeEnum().isDetail()) {
            DetailProductVO detailProductVO = formatProduct4DetailShow(productionOrderProductEntityList, pagingProductDTO);
            pagingProductVO.setProductDataArr(detailProductVO.getProductDataArr());
        }
        pagingProductVO.setPageHelper(pageHelper);
        return pagingProductVO;
    }

    public DetailProductVO formatProduct4DetailShow(List<ProductionOrderProductEntity> productionOrderProductEntityList, PagingProductDTO pagingProductDTO) throws XbbException{
        DetailProductVO detailProductVO = new DetailProductVO();
        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> warehouseIdList = new ArrayList<>();
        Set<String> warehouseKeySet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ProductionOrderProductEntity productionOrderProductEntity : productionOrderProductEntityList) {
            productIds.add(productionOrderProductEntity.getProductId());
            warehouseIdList.add(productionOrderProductEntity.getWarehouseId());
            warehouseKeySet.add(productionOrderProductEntity.getProductId() + "_" + productionOrderProductEntity.getWarehouseId());
        }
        String corpid = pagingProductDTO.getCorpid();
        JSONArray productArray = new JSONArray();
        List<PaasFormDataEntityExt> warehouseList = paasEsModel.getByIdList(warehouseIdList, pagingProductDTO.getCorpid(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WAREHOUSE.getCode(), new ArrayList<>(), IndexTypeEnum.IDX_SAAS_WAREHOUSE);
        Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt paasFormDataEntityExt : warehouseList) {
            JSONObject data = paasFormDataEntityExt.getData();
            warehouseNameMap.put(paasFormDataEntityExt.getId(), FastJsonHelper.getStringOrDefaultFromFormData(data, WarehouseEnum.WAREHOUSE_NAME.getAttr(), ""));
        }
        Map<String, Double> productWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!productIds.isEmpty() && !warehouseIdList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
//            params.put("productIdIn", productIds);
//            params.put("warehouseIdIn", warehouseIdList);
            params.put("warehouseKeyIn",warehouseKeySet);
            List<ProductWarehouseEntity> productWarehouseEntities = productWarehouseModel.findEntitysWithWarehouseChecked(params,null);
            productWarehouseEntities.forEach(item -> {
                String key = item.getProductId() + "_" + item.getWarehouseId();
                productWarehouseMap.put(key, item.getNum());
            });
        }
        Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIds, corpid, DelEnum.NORMAL);
        PaasFormExplainEntity productExplains = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        if (Objects.isNull(productExplains)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> productExplainMap = ExplainUtil.getExplainMap(productExplains.getExplains(), null);
        for (ProductionOrderProductEntity productionOrderProductEntity : productionOrderProductEntityList) {
            Double stock;
            PaasFormDataEntityExt paasFormDataEntityExt = productMap.get(productionOrderProductEntity.getProductId());
            stock = productWarehouseMap.getOrDefault(productionOrderProductEntity.getProductId() + "_" + productionOrderProductEntity.getWarehouseId(), 0D);
            JSONObject json = new JSONObject();
            if (Objects.nonNull(productionOrderProductEntity.getData())) {
                json = productionOrderProductEntity.getData();
            }
            if (Objects.nonNull(productionOrderProductEntity.getBusinessUnit())) {
                productionOrderProductEntity.setProductNum(Arith.div(productionOrderProductEntity.getProductNum(), productionOrderProductEntity.getRate()));
                productionOrderProductEntity.setOutstockNum(Arith.div(productionOrderProductEntity.getOutstockNum(), productionOrderProductEntity.getRate()));
                productionOrderProductEntity.setProductUnit(productionOrderProductEntity.getBusinessUnit().toString());
            }
            for (ProductionOrderMaterielProductEnum productionOrderMaterielProductEnum : ProductionOrderMaterielProductEnum.values()) {
                if (!UpdateDataTypeEnum.DETAIL.formatShow(productionOrderMaterielProductEnum.getShowType())) {
                    continue;
                }
                String attr = productionOrderMaterielProductEnum.getAttr();
                switch (productionOrderMaterielProductEnum) {
                    case PRODUCT:
                        json.put(attr, productionOrderProductEntity.getProductId());
                        break;
                    case WAREHOUSE:
                        if(Objects.equals(pagingProductDTO.getAttr(), ProductionOrderEnum.PRODUCT.getAttr())){
                            break;
                        }
                        JSONArray warehouseArr = productHelp.packegeLinkBusinessJsonArray(productionOrderProductEntity.getWarehouseId(),
                                warehouseNameMap.getOrDefault(productionOrderProductEntity.getWarehouseId(), ""), XbbRefTypeEnum.WAREHOUSE.getCode(), SaasMarkEnum.SAAS.getCode());
                        json.put(attr, warehouseArr);
                        break;
                    case NUM:
                        json.put(attr, productionOrderProductEntity.getProductNum());
                        break;
                    case MEMO:
                        json.put(attr, productionOrderProductEntity.getMemo());
                        break;
                    case UNIT:
                        json.put(attr, productionOrderProductEntity.getProductUnit());
                        break;
                    case LOSS_RATE:
                        json.put(attr, productionOrderProductEntity.getAttritionRate());
                        break;
                    case STOCK:
                        json.put(attr,stock);
                        break;
                    case OUTSTOCK_NUM:
                        json.put(attr,productionOrderProductEntity.getOutstockNum());
                        break;
                    case WAIT_OUTSTOCK_NUM:
                        json.put(attr, Arith.sub(productionOrderProductEntity.getProductNum(),productionOrderProductEntity.getOutstockNum()) > 0 ? Arith.sub(productionOrderProductEntity.getProductNum(),productionOrderProductEntity.getOutstockNum()) : 0);
                        break;
                    default:
                        break;
                }
            }
            json.put(BusinessConstant.PRODUCT_SUB_ID, productionOrderProductEntity.getId());
            productArray.add(json);
        }
        detailProductVO.setProductDataArr(productArray);
        return detailProductVO;
    }




    /**
     * 生产单保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 业务异常
     * @author feng.zheng
     */
    @Override
    public AfterSavePojo afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        AfterSavePojo afterSavePojo = new AfterSavePojo();
        String corpid = saasFormSaveDTO.getCorpid();
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long productionOrderId = newEntity.getId();

        // 保存bom单关联产品
        JSONObject dataList = newEntity.getData();
        Long warehouseId = dataList.getLong(ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr());
        // 通过下面这个特殊的解析产品的方法，在产品数据里加个type标识是否是成品或物料
//        JSONArray productJsonArray = dataList.getJSONArray(ProductionOrderEnum.PRODUCT.getAttr());
//        JSONArray materielJsonArray = dataList.getJSONArray(ProductionOrderEnum.MATERIEL.getAttr());
//        productJsonArray.addAll(materielJsonArray);
//        saveProduct(productJsonArray, corpid, productionOrderId, warehouseId);
        saveProduct2(dataList,corpid,productionOrderId,warehouseId);

        // 团队保存
        afterSavePojo = teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), productionOrderId, saasFormSaveDTO.getNewPaasFormDataEntity(), saasFormSaveDTO.getIsImport(), false);
//        userTeamService.saveUserTeam(saasFormSaveDTO);
        //TODO 日志
        return afterSavePojo;
    }

    private void saveProduct2(JSONObject data, String corpid, Long productionOrderId, Long intoWarehouseId) throws XbbException {
        Map<Long,ProductionOrderProductEntity> originProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<ProductionOrderProductEntity> originProductEntities = productionOrderProductModel.getProductsById(productionOrderId, corpid, null, Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.APPROVE_FAILED.getDel()));
        originProductEntities.forEach(item -> {
            originProductMap.put(item.getId(), item);

        });
        JSONArray finishProductArray = data.getJSONArray(ProductionOrderEnum.PRODUCT.getAttr());
        JSONArray materielProductArray = data.getJSONArray(ProductionOrderEnum.MATERIEL.getAttr());
        JSONArray productArray = new JSONArray();
        productArray.addAll(finishProductArray);
        productArray.addAll(materielProductArray);
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        Integer sort = 0;
        List<ProductionOrderProductEntity> insertList = new ArrayList<>();
        List<ProductionOrderProductEntity> updateList = new ArrayList<>();
        for (int i = 0; i < finishProductArray.size(); i++) {
            JSONObject jsonObject = finishProductArray.getJSONObject(i);
            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            Long businessProductId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            boolean addProductFlag = formDataValidateProductHelp.addProductFlag(businessProductId);
            Double unitNum = jsonObject.getDouble(RelativeProductEnum.UNIT_NUM.getSaasAttr());
            unitNum = unitNum == null ? 1 : unitNum;
            sort++;
            Double productNum = jsonObject.getDouble(ProductionOrderFinishProductEnum.NUM.getAttr());
            ProductionOrderProductEntity productionOrderProductEntity;
            if (addProductFlag) {
                productionOrderProductEntity = new ProductionOrderProductEntity();
                productionOrderProductEntity.setAddTime(DateTimeUtil.getInt());
                productionOrderProductEntity.setUpdateTime(DateTimeUtil.getInt());
                insertList.add(productionOrderProductEntity);
            } else if (originProductMap.containsKey(businessProductId) && Objects.equals(originProductMap.get(businessProductId).getType(), 1)) {
                productionOrderProductEntity = originProductMap.get(businessProductId);
                productionOrderProductEntity.setUpdateTime(DateTimeUtil.getInt());
                if (Objects.equals(DelEnum.APPROVE_FAILED.getDel(), productionOrderProductEntity.getDel())) {
                    productionOrderProductEntity.setDel(DelEnum.NORMAL.getDel());
                }
                updateList.add(productionOrderProductEntity);
                originProductMap.remove(businessProductId);
            }  else {
                continue;
            }
            JSONObject productData = productMap.get(pageProductId).getData();
            productionOrderProductEntity.setCorpid(corpid);
            productionOrderProductEntity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            productionOrderProductEntity.setProductId(pageProductId);
            productionOrderProductEntity.setWarehouseId(intoWarehouseId);
            productionOrderProductEntity.setProductNum(productNum);
            productionOrderProductEntity.setProductUnitNum(unitNum);
            productionOrderProductEntity.setAttritionRate(0D);
            productionOrderProductEntity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            // 保存的是父产品的编号
            productionOrderProductEntity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
            productionOrderProductEntity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            productionOrderProductEntity.setType(1);
            productionOrderProductEntity.setSort(sort);
            productionOrderProductEntity.setProductionOrderId(productionOrderId);
            productionOrderProductEntity.setBarcode(productData.getString(ProductEnum.BARCODE.getAttr()));
            productionOrderProductEntity.setMemo(jsonObject.getString(SelectProductEnum.MEMO.getAttr()));
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, productionOrderProductEntity);
                productionOrderProductEntity.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                productionOrderProductEntity.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(SelectProductEnum.UNIT.getAttr(),productData.getString(ProductEnum.UNIT.getAttr()));
            }
            productionOrderProductEntity.setData(jsonObject);
        }
        for (int i = 0; i < materielProductArray.size(); i++) {
            JSONObject jsonObject = materielProductArray.getJSONObject(i);
            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            Long businessProductId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            saasSaveHelp.formatLinkBusiness4Save(jsonObject,ProductionOrderMaterielProductEnum.WAREHOUSE.getAttr(),"warehouseName",FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            Long warehouseId = jsonObject.getLong(ProductionOrderMaterielProductEnum.WAREHOUSE.getAttr());
            boolean addProductFlag = formDataValidateProductHelp.addProductFlag(businessProductId);
            Double unitNum = jsonObject.getDouble(RelativeProductEnum.UNIT_NUM.getSaasAttr());
            unitNum = unitNum == null ? 0 : unitNum;
            sort++;
            Double productNum = jsonObject.getDouble(BomMaterielProductEnum.NUM.getAttr());
            Double lossRate = jsonObject.getDouble(BomMaterielProductEnum.LOSS_RATE.getAttr());
            ProductionOrderProductEntity productionOrderProductEntity;
            if (addProductFlag) {
                productionOrderProductEntity = new ProductionOrderProductEntity();
                productionOrderProductEntity.setAddTime(DateTimeUtil.getInt());
                productionOrderProductEntity.setUpdateTime(DateTimeUtil.getInt());
                insertList.add(productionOrderProductEntity);
            } else if (originProductMap.containsKey(businessProductId) && Objects.equals(originProductMap.get(businessProductId).getType(), 2)) {
                productionOrderProductEntity = originProductMap.get(businessProductId);
                productionOrderProductEntity.setUpdateTime(DateTimeUtil.getInt());
                if (Objects.equals(DelEnum.APPROVE_FAILED.getDel(), productionOrderProductEntity.getDel())) {
                    productionOrderProductEntity.setDel(DelEnum.NORMAL.getDel());
                }
                updateList.add(productionOrderProductEntity);
                originProductMap.remove(businessProductId);
            }  else {
                continue;
            }
            JSONObject productData = productMap.get(pageProductId).getData();
            productionOrderProductEntity.setCorpid(corpid);
            productionOrderProductEntity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            productionOrderProductEntity.setProductId(pageProductId);
            productionOrderProductEntity.setWarehouseId(warehouseId);
            productionOrderProductEntity.setProductNum(productNum);
            productionOrderProductEntity.setProductUnitNum(unitNum);
            productionOrderProductEntity.setAttritionRate(lossRate);
            productionOrderProductEntity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            // 保存的是父产品的编号
            productionOrderProductEntity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
            productionOrderProductEntity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            productionOrderProductEntity.setType(2);
            productionOrderProductEntity.setSort(sort);
            productionOrderProductEntity.setProductionOrderId(productionOrderId);
            productionOrderProductEntity.setBarcode(productData.getString(ProductEnum.BARCODE.getAttr()));
            productionOrderProductEntity.setMemo(jsonObject.getString(SelectProductEnum.MEMO.getAttr()));
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, productionOrderProductEntity);
                productionOrderProductEntity.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                productionOrderProductEntity.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(SelectProductEnum.UNIT.getAttr(),productData.getString(ProductEnum.UNIT.getAttr()));
            }
            productionOrderProductEntity.setData(jsonObject);
        }

        productionOrderProductModel.inserBatch(insertList);

        productionOrderProductModel.updateMulti(updateList, corpid);
        List<Long> deleteList = new ArrayList<>();
        for (Map.Entry<Long, ProductionOrderProductEntity> entry : originProductMap.entrySet()) {
            ProductionOrderProductEntity delProduct = entry.getValue();
            deleteList.add(delProduct.getId());
        }
        productionOrderProductModel.deleteBatch(deleteList, corpid, DelEnum.DELETE.getDel());
    }


    @Override
    public void saveProduct(JSONArray productArray, String corpid, Long productionOrderId, Long warehouseId) throws XbbException {
        if (productArray == null || corpid == null || productionOrderId == null) {
            return;
        }
        List<Long> pageProductIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        pageProductIds.add(-1L);
        List<Long> dbProductIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        dbProductIds.add(-1L);
        List<Long> addProductIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        addProductIds.add(-1L);
        List<Long> deleteProductIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        deleteProductIds.add(-1L);
        List<ProductionOrderProductEntity> updateProducts = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            // 页面传入的产品id
            Long productId = jsonObject.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
            pageProductIds.add(productId);
        }

        // 获取原生产单的关联产品
        List<ProductionOrderProductEntity> orderProductEntities = productionOrderProductModel.getProductsById(productionOrderId, corpid, null);
        for (ProductionOrderProductEntity orderProductEntity : orderProductEntities) {
            // 数据库中原来的产品id
            dbProductIds.add(orderProductEntity.getProductId());
        }
        // 新增
        for (Long productId : pageProductIds) {
            if (!dbProductIds.contains(productId)) {
                addProductIds.add(productId);
            }
        }
        List<ProductionOrderProductEntity> updateOrderProductEntities = new ArrayList<>();
        // 刪除
        for (ProductionOrderProductEntity orderProductEntity : orderProductEntities) {
            if (!pageProductIds.contains(orderProductEntity.getProductId())) {
                orderProductEntity.setUpdateTime(DateTimeUtil.getInt());
                orderProductEntity.setDel(DelEnum.DELETE.getDel());
                updateOrderProductEntities.add(orderProductEntity);
                deleteProductIds.add(orderProductEntity.getProductId());
            }
        }

        // 编辑
        for (ProductionOrderProductEntity orderProductEntity : orderProductEntities) {
            if (!deleteProductIds.contains(orderProductEntity.getProductId())) {
                updateProducts.add(orderProductEntity);
            }
        }

        // 新增的时候，冗余保存产品的name和编号，规格等信息
        List<String> fieldList = Arrays.asList(StringConstant.SAAS_LINK_BUSINESS_ID, StringConstant.DATA_ID, StringConstant.JSON_DATA);
        Map<String, Map<Long, ProductEntityExt>> resultMap = productModel.getProductWithParentMapByIdIn(corpid, addProductIds, fieldList);
        Map<Long, ProductEntityExt> productMap = resultMap.get(StringConstant.PRODUCT_MAP);
        Map<Long, ProductEntityExt> parentProductMap = resultMap.get(StringConstant.PARENT_PRODUCT_MAP);

        // 产品排序
        Integer sort = 0;
        List<ProductionOrderProductEntity> addOrderProductEntities = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            sort++;
            JSONObject jsonObject = productArray.getJSONObject(i);
            // 页面传入的产品id
            Long pageProductId = jsonObject.getLong("id");
            // 这个值是外部getProductionProduct拿产品的时候硬塞的，只为标识成品或物料
            Integer productType = jsonObject.getInteger("type");
            for (Long productId : addProductIds) {
                if (Objects.equals(pageProductId, productId)) {
                    ProductionOrderProductEntity orderProductEntity = new ProductionOrderProductEntity();
                    if (productMap.containsKey(productId)) {
                        ProductEntityExt product = productMap.get(productId);
                        JSONObject dataList = product.getData();
                        ProductEntityExt parentProduct = parentProductMap.get(dataList.getLong(ProductEnum.PARENT_ID.getAttr()));
                        String productNo = "";
                        if (parentProduct != null) {
                            JSONObject parentDataList = parentProduct.getData();
                            productNo = parentDataList.getString(ProductEnum.PRODUCT_NO.getAttr());
                        }
                        // 产品数量
                        Double productNum;
                        try {
                            productNum = jsonObject.getDouble(RelativeProductEnum.NUM.getSaasAttr());
                        } catch (Exception e) {
                            productNum = 0D;
                        }

                        Double attrition = 0D;
                        if (Objects.equals(productType, 2)) {
                            // 产品损耗率
                            attrition = jsonObject.getDouble(RelativeProductEnum.ATTRITION_RATE.getSaasAttr());
                            JSONObject warehouse = jsonObject.getJSONObject(RelativeProductEnum.WAREHOUSE.getSaasAttr());
                            warehouseId = warehouse.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                        }

                        Double unitNum = jsonObject.getDouble(RelativeProductEnum.UNIT_NUM.getSaasAttr());

                        orderProductEntity.setCorpid(corpid);
                        orderProductEntity.setWarehouseId(warehouseId);
                        orderProductEntity.setParentId(product.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
                        orderProductEntity.setProductId(productId);
                        orderProductEntity.setProductNum(productNum == null ? 0 : productNum);
                        orderProductEntity.setAttritionRate(attrition);
                        orderProductEntity.setProductName(dataList.getString(ProductEnum.NAME.getAttr()));
                        // 保存的是父产品的编号
                        orderProductEntity.setProductNo(productNo);
                        orderProductEntity.setProductSpecification(dataList.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                        orderProductEntity.setProductUnit(dataList.getString(ProductEnum.UNIT.getAttr()));
                        orderProductEntity.setProductUnitNum(unitNum == null ? 0 : unitNum);
                        orderProductEntity.setType(productType);
                        orderProductEntity.setSort(sort);
                        orderProductEntity.setProductionOrderId(productionOrderId);
                        //productionOrderProductModel.save(orderProductEntity);
                        addOrderProductEntities.add(orderProductEntity);
                    }
                    break;
                }
            }

            for (ProductionOrderProductEntity orderProductEntity : updateProducts) {
                if (Objects.equals(orderProductEntity.getProductId(), pageProductId)) {
                    if (Objects.equals(productType, 2)) {
                        JSONObject warehouse = jsonObject.getJSONObject(RelativeProductEnum.WAREHOUSE.getSaasAttr());
                        if (warehouse != null && warehouse.size() > 0) {
                            warehouseId = warehouse.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                            orderProductEntity.setWarehouseId(warehouseId == null ? 0 : warehouseId);
                        }
                    } else {
                        orderProductEntity.setWarehouseId(warehouseId);
                    }
                    Double unitNum = jsonObject.getDouble(RelativeProductEnum.UNIT_NUM.getSaasAttr());
                    orderProductEntity.setProductUnitNum(unitNum == null ? 0 : unitNum);
                    orderProductEntity.setProductNum(jsonObject.getDouble(RelativeProductEnum.NUM.getSaasAttr()));
                    Double attritionRate = jsonObject.getDouble(RelativeProductEnum.ATTRITION_RATE.getSaasAttr());
                    orderProductEntity.setAttritionRate(attritionRate == null ? 0D : attritionRate);
                    orderProductEntity.setSort(sort);
                    //productionOrderProductModel.save(orderProductEntity);
                    updateOrderProductEntities.add(orderProductEntity);
                    break;
                }
            }
        }
        if (!addOrderProductEntities.isEmpty()) {
            productionOrderProductModel.inserBatch(addOrderProductEntities);
        }
        if (!updateOrderProductEntities.isEmpty()) {
            productionOrderProductModel.updateBatch(updateOrderProductEntities, corpid);
        }
    }

    @Override
    public void formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        String corpid = formatExplainDTO.getCorpid();
        List<FieldAttrEntity> fieldAttrEntities = formatExplainDTO.getExplainList();
        String platForm = formatExplainDTO.getPlatform();
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
            String attr = fieldAttrEntity.getAttr();
            if (Objects.equals(attr, ProductionOrderEnum.PLAN_TIME.getAttr())) {
                SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                saasParticularAttributePoJo = saasParticularAttributePoJo == null ? new SaasParticularAttributePoJo() : saasParticularAttributePoJo;
                DefaultAttrPoJo defaultAttrPoJo = fieldAttrEntity.getDefaultAttr();
                if (Objects.isNull(defaultAttrPoJo.getDefaultType())) {
                    defaultAttrPoJo.setDefaultType(DefaultTypeEnum.TODAY.getAlias());
                }
                fieldAttrEntity.setDefaultAttr(defaultAttrPoJo);
                fieldAttrEntity.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
            } else if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())) {
                explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.PRODUCTION_ORDER, corpid, OperatePageEnum.NEW.getCode(), false);
            } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())) {
                explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.PRODUCTION_ORDER, corpid, OperatePageEnum.NEW.getCode(), false);
                if (Objects.equals(platForm, PlatFormEnum.DINGTALK.getValue())) {
                    SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                    saasParticularAttributePoJo.setProductRelyAttr(ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr());
                }
            }
        }
    }


    /**
     * 新建时，把当前用户做为负责人
     *
     * @param productionOrderId 生产单id
     * @param userEntity        当前用户的实体
     * @author long.rao
     * @date 2019-02-21 13:58
     */
    private void saveProductionOrderUser(Long productionOrderId, UserEntity userEntity) throws XbbException {
        long now = DateUtil.getInt();
        ProductionOrderUserEntity productionOrderUserEntity = new ProductionOrderUserEntity();
        productionOrderUserEntity.setCorpid(userEntity.getCorpid());
        productionOrderUserEntity.setUserId(userEntity.getUserId());
        productionOrderUserEntity.setUserName(userEntity.getName());
        productionOrderUserEntity.setUserAvatar(userEntity.getAvatar());
        productionOrderUserEntity.setDataId(productionOrderId);
        productionOrderUserEntity.setIsMain(1);
        productionOrderUserEntity.setAddTime(now);
        productionOrderUserEntity.setUpdateTime(now);
        productionOrderUserModel.save(productionOrderUserEntity);
    }

//    @Override
//    public void formatProduct4Show(JSONObject dataList, SaasAnalysisDataDTO saasAnalysisDataDTO) throws XbbException {
//        if (dataList == null || saasAnalysisDataDTO == null) {
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
//        }
//        // 获取生产单关联产品
//        BusinessProductListDTO businessProductListDTO = new BusinessProductListDTO();
//        BeanUtil.copyProperties(saasAnalysisDataDTO, businessProductListDTO);
//        BusinessProductListVO businessProductListVO;
//        if (saasAnalysisDataDTO.getForProcess()) {
//            businessProductListVO = getProductionOrderProductList(businessProductListDTO, dataList);
//        } else {
//            businessProductListVO = getProductionOrderProductList(businessProductListDTO, null);
//        }
//        JSONObject finishedProductObj = businessProductListVO.getFinishedProduct();
//        JSONObject materielProductObj = businessProductListVO.getMateriel();
//        dataList.put(ProductionOrderEnum.PRODUCT.getAttr(), finishedProductObj);
//        dataList.put(ProductionOrderEnum.MATERIEL.getAttr(), materielProductObj);
//    }

    @Override
    public void formatProduct4Show2(Long dataId, String corpid, JSONObject data, UpdateDataTypeEnum updateDataTypeEnum) throws XbbException {
        productionOrderModel.formatProduct4Show2(dataId, corpid, data, updateDataTypeEnum);
    }

    @Override
    public JSONObject formatSingleProduct(ProductionOrderProductEntity productionOrderProductEntity) {
        return productionOrderModel.formatSingleProduct(productionOrderProductEntity);
    }

    @Override
    public JSONObject formatSingleMaterial(ProductionOrderProductEntity productionOrderProductEntity) {
        JSONObject json = productionOrderProductEntity.getData();
        Double rate = showFormatHelp.approvalSetBusinessUnit(json, productionOrderProductEntity);
        if (Objects.equals(productionOrderProductEntity.getType(), 2)) {
            if (Objects.isNull(json) || json.isEmpty()) {
                json = new JSONObject();
                for (ProductionOrderMaterielProductEnum productionOrderMaterielProductEnum : ProductionOrderMaterielProductEnum.values()) {
                    String attr = productionOrderMaterielProductEnum.getAttr();
                    switch (productionOrderMaterielProductEnum) {
                        case PRODUCT:
                            json.put(attr,productionOrderProductEntity.getProductId());
                        break;
                        case NUM:
                            json.put(attr,productionOrderProductEntity.getProductNum());
                            break;
                        case MEMO:
                            json.put(attr,productionOrderProductEntity.getMemo());
                            break;
                        case LOSS_RATE:
                            json.put(attr,productionOrderProductEntity.getAttritionRate());
                            break;
                        case UNIT:
                            json.put(attr,productionOrderProductEntity.getProductUnit());
                            break;
                        case WAREHOUSE:
                            json.put(attr,productionOrderProductEntity.getWarehouseId());
                            break;
                        default:
                            break;
                    }
                }
            }
            JSONArray jsonArray = new JSONArray();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, productionOrderProductEntity.getWarehouseId());
            jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, json.getString("warehouseName"));
            jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_LINK_TYPE,XbbRefTypeEnum.WAREHOUSE.getCode());
            jsonObject.put("saasMark", SaasMarkEnum.SAAS.getCode());
            jsonArray.add(jsonObject);
            json.put(ProductionOrderMaterielProductEnum.WAREHOUSE.getAttr(),jsonArray);
        }
        json.put(ProductionOrderMaterielProductEnum.OUTSTOCK_NUM.getAttr(), Arith.div(productionOrderProductEntity.getOutstockNum(), rate));
        double waitNum =  Arith.sub(json.getDouble(ProductionOrderMaterielProductEnum.NUM.getAttr()), json.getDouble(ProductionOrderMaterielProductEnum.OUTSTOCK_NUM.getAttr()));
        json.put(ProductionOrderMaterielProductEnum.WAIT_OUTSTOCK_NUM.getAttr(), waitNum < 0 ? 0 : waitNum);
        return json;
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO = new ProductionOrderUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, productionOrderUpdateBatchDTO);
        List<ProductionOrderUpdateDTO> productionOrderList = new ArrayList<>();
        addBatchList.forEach(item ->{
            ProductionOrderUpdateDTO productionOrderUpdateDTO = new ProductionOrderUpdateDTO();
            productionOrderUpdateDTO.setData(item.getData());
            productionOrderUpdateDTO.setId(item.getId());
            productionOrderList.add(productionOrderUpdateDTO);
        });
        productionOrderUpdateBatchDTO.setProductionOrderList(productionOrderList);
        updateBatch(productionOrderUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        String corpid = saasFormSaveDTO.getCorpid();
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long productionOrderId = newEntity.getId();

        // 保存bom单关联产品
        JSONObject dataList = newEntity.getData();
        Long warehouseId = dataList.getLong(ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr());

        saveProduct2(dataList,corpid,productionOrderId,warehouseId);

        // 团队保存
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), productionOrderId, saasFormSaveDTO.getNewPaasFormDataEntity(), saasFormSaveDTO.getIsImport(), true);
//        userTeamService.saveUserTeam(saasFormSaveDTO);
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        String corpid = saasFormSaveDTO.getCorpid();
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long productionOrderId = newEntity.getId();

        // 保存bom单关联产品
        JSONObject dataList = newEntity.getData();
        Long warehouseId = dataList.getLong(ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr());
        saveProduct2(dataList,corpid,productionOrderId,warehouseId);

        // 团队保存
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), productionOrderId, saasFormSaveDTO.getNewPaasFormDataEntity(), saasFormSaveDTO.getIsImport(), true);
    }

    @Override
    public JSONObject getFormatProductJsonArray(FormatProductionOrderProductDTO formatProductionOrderProductDTO) throws XbbException {
        // 获取参数
        ProductionOrderProductEntityExt productionOrderProduct = formatProductionOrderProductDTO.getProductionOrderProductEntityExt();
        Long productId = productionOrderProduct.getProductId();
        Map<String, FieldAttrEntity> nowProductExplainMap = formatProductionOrderProductDTO.getNowProductExplainMap();

        JSONObject productObj = new JSONObject();
        JSONArray attrArray = new JSONArray();

        // 获取关联产品需要展示的字段
        BusinessProductEnum businessProductEnum = BusinessProductEnum.getByCodeAndTargetCode(XbbRefTypeEnum.PRODUCTION_ORDER.getCode(),formatProductionOrderProductDTO.getTargetCode());

        if (businessProductEnum != BusinessProductEnum.UNKNOW) {
            List<RelativeProductEnum> businessProductEnumList = businessProductEnum.getList();

            Integer productType = productionOrderProduct.getType();

            ProductWarehouseMapDTO productWarehouseMapDTO = new ProductWarehouseMapDTO();
            BeanUtil.copyProperties(formatProductionOrderProductDTO, productWarehouseMapDTO);
            productWarehouseMapDTO.setAllWarehouse(0);
            productWarehouseMapDTO.setProductId(productId);
            ProductWarehouseMapVO productWarehouseMapVO = warehouseService.getSelectProductWarehouses(productWarehouseMapDTO);
            if (Objects.isNull(productWarehouseMapVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Map<String, JSONArray> warehouseMap = productWarehouseMapVO.getProductWarehouseMap();
            for (RelativeProductEnum productEnum : businessProductEnumList) {
                String saasAttr = productEnum.getSaasAttr();
                FieldAttrEntity fieldAttrEntity = null;
                if (nowProductExplainMap.containsKey(saasAttr)) {
                    fieldAttrEntity = nowProductExplainMap.get(saasAttr);
                }
                switch (productEnum) {
                    case NAME:
                        JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(NAME, productionOrderProduct.getProductName(), fieldAttrEntity));
                        break;
                    case PRODUCT_NO:
                        JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCT_NO, productionOrderProduct.getProductNo(), fieldAttrEntity));
                        break;
                    case BARCODE:
                        String barcode = productionOrderProduct.getBarcode();
                        barcode = barcode == null ? "" : barcode;
                        JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BARCODE, barcode, fieldAttrEntity));
                        break;
                    case SPECIFICATION:
                        // 格式化规格
                        String specification = specificationModel.joinSpecification(productionOrderProduct.getProductSpecification());
                        JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(SPECIFICATION, specification, fieldAttrEntity));
                        break;
                    case WAREHOUSE:
                        if (Objects.equals(productType, 2)) {
                            // 物料产品才有仓库信息
                            JSONObject warehouseObj = productionOrderProduct.getWarehouseObj();

                            JSONObject object = saasUpdateHelp.formatSelectProduct4Show(WAREHOUSE, warehouseObj, fieldAttrEntity);
                            if(object != null) {
                                JSONArray warehouseArray = warehouseMap.get("userWarehouseArray");
                                object.put("attrName", I18nMessageUtil.getMessage(StringConstant.OUT_WAREHOUSE));
                                object.put("warehouseArray", warehouseArray);
                                attrArray.add(object);
                            }
                        }
                        break;
                    case UNIT_NUM:
                        Double unitNum = productionOrderProduct.getProductUnitNum();
                        unitNum = unitNum == null ? 0 : unitNum;
                        JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(UNIT_NUM, unitNum, fieldAttrEntity));
                        break;
                    case NUM:
                        if(Objects.isNull(fieldAttrEntity)) {
                            fieldAttrEntity = new FieldAttrEntity();
                        }
                        FieldAttrEntity stockAttrEntity = nowProductExplainMap.get(ProductEnum.STOCK.getSaasAttr());
                        if(Objects.nonNull(stockAttrEntity)) {
                            fieldAttrEntity.setAccuracy(stockAttrEntity.getAccuracy());
                        }
                        Double num = productionOrderProduct.getProductNum();
                        num = num == null ? 0 : num;
                        JSONObject numObj = saasUpdateHelp.formatSelectProduct4Show(NUM, num, fieldAttrEntity);
                        if(numObj != null) {
                            if (Objects.equals(productType, 2)) {
                                numObj.put("attrName", ProductionOrderMaterielProductEnum.NUM.getAttrName());
                            } else {
                                numObj.put("attrName", ProductionOrderFinishProductEnum.NUM.getAttrName());
                            }
                            attrArray.add(numObj);
                        }
                        break;
                    case STOCK:
                        Double stock = productionOrderProduct.getStock();
//                        Double stock = productionOrderProduct.getStock();

                        Map<String ,Object> param = new HashMap<>();
                        param.put("productId",productionOrderProduct.getProductId());
//                        param.put("warehouseId",productionOrderProduct.getWarehouseId());
                        param.put("del",0L);
                        param.put("corpid",formatProductionOrderProductDTO.getCorpid());
                        List<ProductWarehouseEntity> entitys = productWarehouseModel.findEntitysWithWarehouseChecked(param,null);
                        Double sum=0D;
                        for (ProductWarehouseEntity entity : entitys) {
                            sum+=entity.getNum();
                        }
//                        Double stock = productionOrderProduct.getStock();
                        stock = stock == null || productionOrderProduct.getWarehouseId()==null ? sum : stock;
                        JSONObject stockObj = saasUpdateHelp.formatSelectProduct4Show(STOCK, stock, fieldAttrEntity);
                        if (stockObj != null) {
                            attrArray.add(stockObj);
                        }
                        break;
                    case UNIT:
                        String productUnit = productionOrderProduct.getProductUnit();
                        String unitStr = fieldAttrHelp.getDataDictionaryTextByValue(productUnit, fieldAttrEntity);
                        JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(UNIT, unitStr, fieldAttrEntity));
                        break;
                    case ATTRITION_RATE:
                        if (Objects.equals(productType, 2)) {
                            // 物料产品才有损耗率
                            JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(ATTRITION_RATE, productionOrderProduct.getAttritionRate(), fieldAttrEntity));
                        }
                        break;
                    case THUMBNAIL:
                        JSONArray imageList = productionOrderProduct.getImageUrlArray() == null ? new JSONArray() : productionOrderProduct.getImageUrlArray();
                        productObj.put(ProductEnum.THUMBNAIL.getSaasAttr(), imageList);
                        if (Objects.equals(formatProductionOrderProductDTO.getPlatform(), StringConstant.PLATFORM_DINGTALK)) {
                            JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(THUMBNAIL, productionOrderProduct.getImageUrlArray(), fieldAttrEntity));
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        productObj.put("result", attrArray);
        productObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, productionOrderProduct.getProductId());
        productObj.put(StringConstant.BUSINESS_PRODUCT_ID, productionOrderProduct.getId());
        productObj.put("parentId", productionOrderProduct.getParentId());
        // TODO 库存产品自定义字段的回显
        return productObj;
    }

    @Override
    public ProductionOrderListVO findProductionOrderList(ProductionOrderListDTO productionOrderListDTO) throws XbbException {
        ProductionOrderListVO productionOrderListVO = new ProductionOrderListVO();
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(productionOrderListDTO, true);
            param.put("idIn", productionOrderListDTO.getRefIdIn());
            List<ProductionOrderEntityExt> productionOrderList = productionOrderModel.findEntitys(param);
            if (Objects.isNull(productionOrderList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            productionOrderListVO.setProductionOrderList(productionOrderList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productionOrderServiceImpl.findProductionOrderList 查询出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productionOrderListVO;
    }

    @Override
    public ProductionOrderUpdateBatchVO updateBatch(ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO) throws XbbException {
        ProductionOrderUpdateBatchVO productionOrderUpdateBatchVO = new ProductionOrderUpdateBatchVO();
        try {
            String corpid = productionOrderUpdateBatchDTO.getCorpid();
            if (Objects.nonNull(productionOrderUpdateBatchDTO.getProductionOrderList())
                    && !productionOrderUpdateBatchDTO.getProductionOrderList().isEmpty()) {
                List<UpdateDataEntity> list = new ArrayList<>();
                productionOrderUpdateBatchDTO.getProductionOrderList().forEach((item) -> {
                    list.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
                if (!list.isEmpty()) {
                    productionOrderModel.updateBatch(list, corpid);
                }
            }
        } catch (Exception e) {
            LOG.error("productionOrderServiceImpl.updateBatch 批量更新出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productionOrderUpdateBatchVO;
    }

    @Override
    public ProductionOrderUpdateBatchVO updateBatchImmediately(ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO) throws XbbException {
        ProductionOrderUpdateBatchVO productionOrderUpdateBatchVO = new ProductionOrderUpdateBatchVO();
        try {
            String corpid = productionOrderUpdateBatchDTO.getCorpid();
            if (Objects.nonNull(productionOrderUpdateBatchDTO.getProductionOrderList())
                    && !productionOrderUpdateBatchDTO.getProductionOrderList().isEmpty()) {
                List<UpdateDataEntity> list = new ArrayList<>();
                productionOrderUpdateBatchDTO.getProductionOrderList().forEach((item) -> {
                    list.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
                if (!list.isEmpty()) {
                    productionOrderModel.updateBatchImmediately(list, corpid);
                }
            }
        } catch (Exception e) {
            LOG.error("productionOrderServiceImpl.updateBatch 批量更新出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productionOrderUpdateBatchVO;
    }

    /**
     * 获取可退料入库的产品和数量
     *
     * @param retMaterielListDTO
     * @return
     */
    @Override
    public RetMaterielListVO getRetMaterielMap(RetMaterielListDTO retMaterielListDTO) throws XbbException {
        RetMaterielListVO retMaterielListVO = new RetMaterielListVO();
        try {
            String corpid = retMaterielListDTO.getCorpid();
            Map<Long, Map<Long, Double>> outstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> instockIdIn = new ArrayList<>();
            List<Long> instockProductOrderIdIn = retMaterielListDTO.getInstockIdIn();
            List<Long> outstockProductOrderIdIn = retMaterielListDTO.getOutstockIdIn();
            List<ProductionOrderEntityExt> productionOrderList = new ArrayList<>();
            Map<Long, Long> productOrderInstockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> param = BeanUtil.convertBean2Map(retMaterielListDTO, true);
            Set<Long> productionOrderIds = new HashSet<>();
            if (CollectionsUtil.isNotEmpty(instockProductOrderIdIn)) {
                param.put("idIn", instockProductOrderIdIn);
                productionOrderList = productionOrderModel.findEntitys(param);
                if (Objects.isNull(productionOrderList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                productionOrderList.forEach(item->{
                    productionOrderIds.add(item.getId());
                });
            } else if (CollectionsUtil.isNotEmpty(outstockProductOrderIdIn)) {
                Map<Long, OutstockEntityExt> materielOutstockMap = retMaterielListDTO.getMaterielOutstockMap();
                param.put("idIn", outstockProductOrderIdIn);
                productionOrderList = productionOrderModel.findEntitys(param);
                if (Objects.isNull(productionOrderList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                Iterator<ProductionOrderEntityExt> iterator = productionOrderList.iterator();

                while (iterator.hasNext()) {
                    ProductionOrderEntityExt item = iterator.next();
                    if (materielOutstockMap.containsKey(item.getId())) {
                        OutstockEntityExt entity = materielOutstockMap.get(item.getId());
                        JSONObject data = item.getData();
                        if (Objects.nonNull(data) && Objects.nonNull(data.getJSONArray(ProductionOrderEnum.OUTSTOCK_ID.getAttr()))) {
                            JSONArray idsArray = data.getJSONArray(ProductionOrderEnum.OUTSTOCK_ID.getAttr());
                            for (int i = idsArray.size() - 1; i >= 0; i--) {
                                Long delId = idsArray.getLong(i);
                                if (Objects.equals(delId, entity.getId())) {
                                    idsArray.remove(i);
                                    break;
                                }
                            }
                        }
                    }
                    productionOrderIds.add(item.getId());
                }
            }
            if (CollectionsUtil.isNotEmpty(productionOrderIds)) {
                // 根据生产单id查询入库id
                InstockListDTO instockListDTO = new InstockListDTO();
                instockListDTO.setCorpid(retMaterielListDTO.getCorpid());
                instockListDTO.setRefIdIn(new ArrayList<>(productionOrderIds));
                instockListDTO.setFieldList(Arrays.asList(StringConstant.DATA_ID, StringConstant.JSON_DATA + StringConstant.POINT + InstockEnum.REF_ID.getAttr()));
                instockListDTO.setType(InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
                instockListDTO.setFlowStatusIn(Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()));
                List<Long> delInstockIdList = retMaterielListDTO.getDelInstockIdList();
                if (delInstockIdList != null && delInstockIdList.size() > 0) {
                    instockListDTO.setMustNotIdIn(delInstockIdList);
                }
                // TODO 获取生产单排除了当前已经删除的退料入库单后的关联的其他退料入库单，这里主动排除了审批中的数据，和transfer那边又有点不一致
                InstockListVO instockListVO = instockService.findInstockList(instockListDTO);
                if (Objects.nonNull(instockListVO)) {
                    List<PaasFormDataEntityExt> instockList = instockListVO.getInstockList();
                    if (CollectionsUtil.isNotEmpty(instockList)) {
                        instockList.forEach(item->{
                            instockIdIn.add(item.getDataId());
                            JSONObject data = item.getData();
                            Long productOrderId = data.getLong(InstockEnum.REF_ID.getAttr());
                            if (Objects.nonNull(productOrderId)) {
                                productOrderInstockMap.put(item.getDataId(), productOrderId);
                            }
                        });
                    }
                }
            }

            JSONArray outStockIds = new JSONArray();
            Map<Long, Long> productOrderOutstockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ProductionOrderEntityExt productionOrderEntityExt : productionOrderList) {
                JSONObject data = productionOrderEntityExt.getData();
                if (Objects.nonNull(data) && Objects.nonNull(data.getJSONArray(ProductionOrderEnum.OUTSTOCK_ID.getAttr()))) {
                    outStockIds.addAll(data.getJSONArray(ProductionOrderEnum.OUTSTOCK_ID.getAttr()));
                    String outstockStr = JSON.toJSONString(data.get(ProductionOrderEnum.OUTSTOCK_ID.getAttr()));
                    List<Long> outstockIdsList = JSON.parseArray(outstockStr, Long.class);
                    // 遍历出库单，把生产单跟出库单绑定
                    outstockIdsList.forEach(item->{
                        productOrderOutstockMap.put(item, productionOrderEntityExt.getId());
                    });
                }
            }
            Set<Long> outstockIdsSet = new HashSet<>();
            for (Object item : outStockIds) {
                Long outstockId = Long.parseLong(String.valueOf(item));
                outstockIdsSet.add(outstockId);
            }
            List<Long> outstockIdList = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(outstockIdsSet)) {
                param.clear();
                param.put(StringConstant.CORPID, corpid);
                param.put("idIn", outstockIdsSet);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                List<OutstockEntityExt> outstockEntityExts = outstockModel.findEntitys(param);
                if (Objects.isNull(outstockEntityExts)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                outstockEntityExts.forEach(item->{
                    outstockIdList.add(item.getId());
                });
            }
            if (CollectionsUtil.isNotEmpty(outstockIdList)) {
                OutstockProductListDTO outstockProductListDTO = new OutstockProductListDTO();
                BeanUtil.copyProperties(retMaterielListDTO, outstockProductListDTO);
                outstockProductListDTO.setOutstockIdIn(outstockIdList);
                OutstockProductListVO outstockProductListVO = outstockProductService.findOutstockProduct(outstockProductListDTO);
                if (Objects.isNull(outstockProductListVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                List<OutstockProductEntity> outstockProductList = outstockProductListVO.getOutstockProductList();
                outstockProductList.forEach((item) -> {
                    Long productId = item.getProductId();
                    Long outstockId = item.getOutWarehouseId();
                    Long productOrderId = productOrderOutstockMap.get(outstockId);
                    // 判断生产单是否有数据
                    if (outstockProductMap.containsKey(productOrderId)) {
                        Map<Long, Double> numMap = outstockProductMap.get(productOrderId);
                        double num = numMap.get(productId) == null ? 0D : numMap.get(productId);
                        numMap.put(productId, Arith.add(item.getProductNum(), num));
                        outstockProductMap.put(productOrderId, numMap);
                    } else {
                        Map<Long, Double> numMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        double num = numMap.get(productId) == null ? 0D : numMap.get(productId);
                        numMap.put(productId, Arith.add(item.getProductNum(), num));
                        outstockProductMap.put(productOrderId, numMap);
                    }
                });
            }
            if (Objects.nonNull(instockIdIn) && !instockIdIn.isEmpty()) {
                Map<String, Object> instockProductParam = BeanUtil.convertBean2Map(retMaterielListDTO, true);
                instockProductParam.put("instockIdIn", instockIdIn);
                List<InstockProductEntity> instockProductList = instockProductModel.findEntitys(instockProductParam);
                if (Objects.isNull(instockProductList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                if (instockProductList != null && instockProductList.size() > 0) {
                    for (InstockProductEntity entity : instockProductList) {
                        Long productId = entity.getProductId();
                        Long instockId = entity.getIntoWarehouseId();
                        Long productOrderId = productOrderInstockMap.get(instockId);
                        if (outstockProductMap.containsKey(productOrderId)) {
                            Map<Long, Double> numMap = outstockProductMap.get(productOrderId);
                            if (numMap.containsKey(productId)) {
                                Double num = numMap.get(productId);
                                Double newNum = Arith.sub(num, entity.getProductNum());
                                if (newNum <= 0) {
                                    outstockProductMap.remove(productOrderId);
                                } else {
                                    numMap.put(productId, newNum);
                                    outstockProductMap.put(productOrderId, numMap);
                                }
                            }

                        }
                    }
                }
            }
            retMaterielListVO.setOutstockProductMap(outstockProductMap);
            retMaterielListVO.setProductionOrderList(productionOrderList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("instockServiceImpl.getRetMaterielMap 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return retMaterielListVO;
    }

    /**
     * 获取可退料入库的产品和数量
     *
     * @param productionOrder 生产单实体
     * @return Map，key为productId，value为可退料入库的数量；如果返回null，则没有可退料入库产品
     * @author lcx
     * @date 2019/2/25 11:00
     **/
    @Override
    public Map<Long, Double> getRetMaterielMap(ProductionOrderEntityExt productionOrder) throws XbbException {
        Long dataId = productionOrder.getId();
        String corpid = productionOrder.getCorpid();
        // 获取已经出库的物料产品
        JSONObject dataList = productionOrder.getData();
        String ids = dataList.getString(ProductionOrderEnum.OUTSTOCK_ID.getAttr());
        JSONArray outstockIds = JSONArray.parseArray(ids);
        if (outstockIds == null || outstockIds.size() == 0) {
            return null;
        }
        // 判断出单库id是否在审批中，在审批中或者待审批则移除
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, 0);
        param.put(ParameterConstant.ID_IN, outstockIds);
        List<OutstockEntityExt> outstockEntities = outstockModel.findEntitys(param);
        if (outstockEntities != null && outstockEntities.size() > 0) {
            for (OutstockEntityExt entity : outstockEntities) {
                Integer flowStatus = entity.getFlowStatus();
                if (!FlowStatusEnum.NOT_NEED_APPROVAL.getType().equals(flowStatus) && !FlowStatusEnum.PASS.getType().equals(flowStatus)) {
                    Long outstockId = entity.getId();
                    if (outstockIds.contains(outstockId)) {
                        outstockIds.remove(outstockId);
                    }
                }
            }
        }
        if (outstockIds.size() == 0) {
            // 物料出库单全部都在审批中，返回null
            return null;
        }
        // 根据出库单id计算已经出库的物料数量，存到map中，key为产品id，value为已出库数量
        param.clear();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, 0);
        param.put("outstockIdIn", outstockIds);
        Map<Long, Double> outstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<OutstockProductEntity> outstockProducts = outstockProductModel.findEntitys(param);
        if (outstockProducts != null && outstockProducts.size() > 0) {
            for (OutstockProductEntity oProduct : outstockProducts) {
                Long productId = oProduct.getProductId();
                double num = outstockProductMap.get(productId) == null ? 0D : outstockProductMap.get(productId);
                outstockProductMap.put(productId, Arith.add(oProduct.getProductNum(), num));
            }
        }
        // 计算已经退料入库的数量
        PaasFormDataEsListVO instockListFromEs = instockService.getInstockListFromEs(corpid, dataId, InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
        List<PaasFormDataEntityExt> instockEntities = instockListFromEs.getPaasFormDataESList();

        List<Long> instockIdIn = new ArrayList<>();
        if (instockEntities != null && instockEntities.size() > 0) {
            for (PaasFormDataEntityExt entity : instockEntities) {
                instockIdIn.add(entity.getDataId());
            }
        }
        if (instockIdIn.size() > 0) {
            // 有对应的退料入库单
            param.clear();
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, 0);
            param.put("instockIdIn", instockIdIn);
            List<InstockProductEntity> instockProductEntities = instockProductModel.findEntitys(param);
            if (instockProductEntities != null && instockProductEntities.size() > 0) {
                for (InstockProductEntity entity : instockProductEntities) {
                    Long productId = entity.getProductId();
                    if (outstockProductMap.containsKey(productId)) {
                        Double num = outstockProductMap.get(productId);
                        Double newNum = Arith.sub(num, entity.getProductNum());
                        if (newNum <= 0) {
                            outstockProductMap.remove(productId);
                        } else {
                            outstockProductMap.put(productId, newNum);
                        }
                    }
                }
            }
        }
        return outstockProductMap;
    }

    @Override
    public Map<Long, OutstockProductEntity> getMaterielAvgCost(ProductionOrderEntityExt productionOrder) {
        String corpid = productionOrder.getCorpid();
        JSONObject dataList = productionOrder.getData();
        // 获取已经出库的物料产品
        String ids = dataList.getString(ProductionOrderEnum.OUTSTOCK_ID.getAttr());
        JSONArray outstockIds = JSONArray.parseArray(ids);
        if (outstockIds == null || outstockIds.size() == 0) {
            return null;
        }
        // 判断出单库id是否在审批中，在审批中或者待审批则移除
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, 0);
        param.put(ParameterConstant.ID_IN, outstockIds);
        List<OutstockEntityExt> outstockEntities = outstockModel.findEntitys(param);
        if (outstockEntities != null && outstockEntities.size() > 0) {
            for (OutstockEntityExt entity : outstockEntities) {
                Integer flowStatus = entity.getFlowStatus();
                if (!FlowStatusEnum.NOT_NEED_APPROVAL.getType().equals(flowStatus) && !FlowStatusEnum.PASS.getType().equals(flowStatus)) {
                    Long outstockId = entity.getId();
                    if (outstockIds.contains(outstockId)) {
                        outstockIds.remove(outstockId);
                    }
                }
            }
        }
        if (outstockIds.size() == 0) {
            // 物料出库单全部都在审批中，返回null
            return null;
        }
        // 根据出库单id计算已经出库的物料数量，存到map中，key为产品id，value为已出库数量
        param.clear();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, 0);
        param.put("outstockIdIn", outstockIds);
        List<OutstockProductEntity> outstockProducts = outstockProductModel.findEntitys(param);
        Map<Long, OutstockProductEntity> outstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (outstockProducts != null && outstockProducts.size() > 0) {
            for (OutstockProductEntity oProduct : outstockProducts) {
                Long productId = oProduct.getProductId();
                OutstockProductEntity productEntity = outstockProductMap.get(productId);
                Double oNum = oProduct.getProductNum();
                Double oCost = oProduct.getCost();
                if (productEntity != null) {
                    Double cost = productEntity.getCost();
                    Double num = productEntity.getProductNum();
                    Double nowNum = Arith.add(oNum, num);
                    Double nowCost = Arith.div(Arith.add(Arith.mul(oNum, oCost), Arith.mul(cost, num)), nowNum);
                    productEntity.setProductNum(nowNum);
                    productEntity.setCost(nowCost);
                } else {
                    productEntity = new OutstockProductEntity();
                    productEntity.setCost(oCost);
                    productEntity.setProductNum(oNum);
                }
                outstockProductMap.put(productId, productEntity);
            }
        }
        return outstockProductMap;
    }

    @Override
    public Map<Long, Double> getMaterielProductNum(ProductionOrderEntityExt productionOrder, List<ProductionOrderProductEntity> poProducts) throws XbbException {
        String corpid = productionOrder.getCorpid();
        // 获取生产单关联的物料出库单
        PaasFormDataEsListVO list = outstockService.getOutstockListFromEs(corpid, productionOrder.getId(), OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode(), 0);
        List<PaasFormDataEntityExt> outstockEntities = list.getPaasFormDataESList();

        List<Long> outIds = new ArrayList<>();
        outIds.add(-1L);
        for (PaasFormDataEntityExt entity : outstockEntities) {
            outIds.add(entity.getDataId());
        }
        // 获取出库单关联的产品
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, 0);
        param.put("outstockIdIn", outIds);
        List<OutstockProductEntity> outstockProductEntities = outstockProductModel.findEntitys(param);
        Map<Long, Double> pNumMap = new HashMap<>();
        // 合并出库单产品的数量
        for (OutstockProductEntity entity : outstockProductEntities) {
            Double num = pNumMap.get(entity.getProductId());
            if (num == null) {
                num = 0D;
            }
            num += entity.getProductNum();
            pNumMap.put(entity.getProductId(), num);
        }
        // 产品物料数量减去已出库数量
        for (ProductionOrderProductEntity entity : poProducts) {
            if (Objects.equals(entity.getType(), 2)) {
                // 物料产品才放入map中
                Double outstockNum = pNumMap.get(entity.getProductId());
                if (outstockNum == null) {
                    // 该产品没有出过库，可出库数量为领料数量
                    pNumMap.put(entity.getProductId(), entity.getProductNum());
                } else {
                    double num = Arith.sub(entity.getProductNum(), outstockNum);
                    num = num < 0 ? 0D : num;
                    pNumMap.put(entity.getProductId(), num);
                }
            }
        }
        return pNumMap;
    }

    /**
     * 判断是否有退料入库的产品
     *
     * @param productionOrder
     * @return true：有，false：没有
     * @author chaoxiong.lei
     */
    @Override
    public boolean hasReturnedMaterielInstock(ProductionOrderEntityExt productionOrder) throws XbbException {
        Map<Long, Double> metMaterielMap = getRetMaterielMap(productionOrder);
        return  metMaterielMap != null && metMaterielMap.size() > 0;
    }


    @Override
    public ProductionOrderDeleteBatchVO deleteBatch(ProductionOrderDeleteBatchDTO productionOrderDeleteBatchDTO) throws XbbException {
        ProductionOrderDeleteBatchVO productionOrderDeleteBatchVO = new ProductionOrderDeleteBatchVO();
        try {
            // TODO 删除权限校验
            // TODO 老板、超管、负责人有删除单据的权限
            List<Long> productionOrderIdIn = productionOrderDeleteBatchDTO.getDataIdList();
            String corpid = productionOrderDeleteBatchDTO.getCorpid();
            Map<String, Object> param = BeanUtil.convertBean2Map(productionOrderDeleteBatchDTO, true);
            param.put("idIn", productionOrderIdIn);
            List<ProductionOrderEntityExt> productionOrderList = productionOrderModel.findEntitys(param);
            if (Objects.isNull(productionOrderList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            //查询编号
            List<String> no= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(ProductionOrderEntityExt entityExt : productionOrderList){
                String sheetNo = entityExt.getSerialNo();
                no.add(sheetNo);
            }
            List<Long> productionOrderIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> productionOrderSerialNoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 如果该【生产单】已生成【生产入库单】，则不允许删除
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder queryBuilder = boolQuery();
            queryBuilder.filter(termQuery("corpid.keyword", corpid));
            queryBuilder.filter(termsQuery("data." + InstockEnum.REF_ID.getAttr(), productionOrderIdIn));
            queryBuilder.filter(termQuery("data." + InstockEnum.TYPE.getAttr(), InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode()));
            queryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            // 设置join_field
            queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCTION_INSTOCK.getType()));
            searchSourceBuilder.query(queryBuilder);
            List<PaasFormDataEntityExt> productInstockList = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_PRODUCTION_INSTOCK, Collections.singletonList(InstockEnum.REF_ID.getAttr()), null, null);
            if (Objects.nonNull(productInstockList) && productInstockList.size() > 0) {
                productInstockList.forEach(item -> {
                    Long productionOrderId = item.getData().getLong(InstockEnum.REF_ID.getAttr());
                    productionOrderIdList.add(productionOrderId);
                });
                for (ProductionOrderEntityExt productionOrderEntityExt : productionOrderList) {
                    if (productionOrderIdList.contains(productionOrderEntityExt.getId())) {
                        productionOrderSerialNoList.add(productionOrderEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(ProductionOrderErrorCodeEnum.API_ERROR_243040, String.format(ProductionOrderErrorCodeEnum.API_ERROR_243040.getMsg(), productionOrderSerialNoList.toString()));
            }
            // 如果该【生产单】已生成【生产领料单】，则不允许删除
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            queryBuilder = boolQuery();
            queryBuilder.filter(termQuery("corpid.keyword", corpid));
            queryBuilder.filter(termsQuery("data." + OutstockEnum.REF_ID.getAttr(), productionOrderIdIn));
            queryBuilder.filter(termQuery("data." + OutstockEnum.TYPE.getAttr(), OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode()));
            queryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            // 设置join_field
            queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCTION_MATERIEL_OUTSTOCK.getType()));
            sourceBuilder.query(queryBuilder);
            List<PaasFormDataEntityExt> materielOutStockList = paasEsModel.list(sourceBuilder, IndexTypeEnum.IDX_SAAS_PRODUCTION_MATERIEL_OUTSTOCK, Collections.singletonList(OutstockEnum.REF_ID.getAttr()), null, null);
            if (Objects.nonNull(materielOutStockList) && materielOutStockList.size() > 0) {
                materielOutStockList.forEach(item -> {
                    Long productionOrderId = item.getData().getLong(OutstockEnum.REF_ID.getAttr());
                    productionOrderIdList.add(productionOrderId);
                });
                for (ProductionOrderEntityExt productionOrderEntityExt : productionOrderList) {
                    if (productionOrderIdList.contains(productionOrderEntityExt.getId())) {
                        productionOrderSerialNoList.add(productionOrderEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(ProductionOrderErrorCodeEnum.API_ERROR_243041, String.format(ProductionOrderErrorCodeEnum.API_ERROR_243041.getMsg(), productionOrderSerialNoList.toString()));
            }

            if(!productionOrderIdIn.isEmpty()) {
                if(BasicConstant.ONE.equals(productionOrderDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(productionOrderIdIn.size())){
                    productionOrderModel.deleteByKey(productionOrderIdIn.get(0),corpid);
                }else {
                    // 删除生产单
                    productionOrderModel.deleteBatch(productionOrderIdIn, corpid);
                }
                productionOrderDeleteBatchVO.setDeleteIds(productionOrderIdIn);
            }
            // 删除负责人和协同人
            ProductionOrderUserDeleteBatchDTO productionOrderUserDeleteBatchDTO = new ProductionOrderUserDeleteBatchDTO();
            BeanUtil.copyProperties(productionOrderDeleteBatchDTO, productionOrderUserDeleteBatchDTO);
            productionOrderUserDeleteBatchDTO.setProductOrderIdIn(productionOrderIdIn);
            productionOrderUserService.deleteBatch(productionOrderUserDeleteBatchDTO);
            // 删除关联产品
            ProductionOrderProductDeleteBatchDTO productionOrderProductDeleteBatchDTO = new ProductionOrderProductDeleteBatchDTO();
            BeanUtil.copyProperties(productionOrderDeleteBatchDTO, productionOrderProductDeleteBatchDTO);
            productionOrderProductDeleteBatchDTO.setProductOrderIdIn(productionOrderIdIn);
            productionOrderProductService.deleteBatch(productionOrderProductDeleteBatchDTO);
            // TODO 删除审批记录
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, productionOrderDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = productionOrderDeleteBatchDTO.getUserId();
            String userName = productionOrderDeleteBatchDTO.getLoginUserName();
            String nameStr = StringUtils.join(no, "，");
            if(productionOrderIdIn.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.PRODUCTION_ORDER.getName(), productionOrderIdIn.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(ProductionOrderEnum.SHEET_NO.getAttrName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.PRODUCTION_ORDER, operateTypeEnum,
                        "", "", memo, productionOrderDeleteBatchDTO.getHttpHeader());
            } else if (Objects.equals(productionOrderIdIn.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.PRODUCTION_ORDER.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PRODUCTION_ORDER, operateTypeEnum,
                        productionOrderIdIn.get(0).toString(), nameStr, memo, productionOrderDeleteBatchDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            LOG.error("productionOrderServiceImpl.deleteBatch 执行出错:", e);
            throw e;
        } catch (Exception e) {
            LOG.error("productionOrderServiceImpl.deleteBatch 执行出错:", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productionOrderDeleteBatchVO;
    }

    @Override
    public void updateReturnedMaterielInstock(InstockProductDeleteBatchVO instockProductDeleteBatchVO,RetMaterielListDTO retMaterielListDTO, Integer businessType) throws XbbException {
        try {
            RetMaterielListVO retMaterielListVO = getRetMaterielMap(retMaterielListDTO);
            if (Objects.isNull(retMaterielListDTO)) {
               throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<Long> outstockProductionOrderIdIn = retMaterielListDTO.getOutstockIdIn();
            Map<Long, Map<Long, Double>> outstockProductMap = retMaterielListVO.getOutstockProductMap();
            List<ProductionOrderEntityExt> productionOrderList = retMaterielListVO.getProductionOrderList();
            if (!outstockProductMap.isEmpty() || CollectionsUtil.isNotEmpty(productionOrderList)) {
                ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO = new ProductionOrderUpdateBatchDTO();
                BeanUtil.copyProperties(retMaterielListDTO, productionOrderUpdateBatchDTO);
                List<ProductionOrderUpdateDTO> updateProductionOrderList = new ArrayList<>();
                productionOrderList.forEach((item) -> {
                    ProductionOrderUpdateDTO updateDataEntity = new ProductionOrderUpdateDTO();
                    updateDataEntity.setId(item.getId());
                    updateDataEntity.setCorpid(item.getCorpid());
                    JSONObject updateData = new JSONObject();
                    JSONObject data = item.getData();
                    Map<Long, Double> numMap = outstockProductMap.get(item.getId());
                    if (Objects.isNull(numMap) || numMap.isEmpty()) {
                        // 不可以退料入库
                        updateData.put(ProductionOrderEnum.HAS_RETURNED_MATERIEL.getAttr(), 0);
                    } else {
                        // 可以退料入库
                        updateData.put(ProductionOrderEnum.HAS_RETURNED_MATERIEL.getAttr(), 1);
                    }
                    if (CollectionsUtil.isNotEmpty(outstockProductionOrderIdIn)) {
                        // 删除出库单需要更新的字段数据
                        updateData.put(ProductionOrderEnum.ALL_OUTBOUND.getAttr(), 0);
                        updateData.put(ProductionOrderEnum.OUTSTOCK_ID.getAttr(), data.get(ProductionOrderEnum.OUTSTOCK_ID.getAttr()));
                    }
                    updateDataEntity.setData(updateData);
                    updateProductionOrderList.add(updateDataEntity);
                    productionOrderUpdateBatchDTO.setProductionOrderList(updateProductionOrderList);
                });
                updateBatch(productionOrderUpdateBatchDTO);
            }
            List<Long> instockIdIn = retMaterielListDTO.getInstockIdIn();
            String corpid = retMaterielListDTO.getCorpid();
            //删除退料入库单后，修改生产单的 是否有（能）退料入库，领料出库单产品表的 入库数量
            if(Objects.equals(businessType, InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode())&&!instockIdIn.isEmpty()){
                List<InstockProductEntity> instockProductList = instockProductDeleteBatchVO.getInstockProductList();
                Map<Long, Double> refProductIdNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

                for(InstockProductEntity instockProductEntity : instockProductList){
                    Long refProductId = instockProductEntity.getRefProductId();
                    if(refProductId != null){
                        Double num = refProductIdNumMap.get(refProductId) == null?0D:refProductIdNumMap.get(refProductId);
                        refProductIdNumMap.put(refProductId,Arith.add(num , instockProductEntity.getProductNum()));
                    }
                }

                if(!refProductIdNumMap.isEmpty()){
                    //查询需要行对应更新的领料出库单产品
                    HashSet<Long> refIds = new HashSet<>();
                    Map<String, Object> params1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    params1.put("corpid", corpid);
                    params1.put("idIn", refProductIdNumMap.keySet());
                    params1.put("del", DelEnum.NORMAL.getDel());
                    List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(params1);

                    if(!CollectionUtils.isEmpty(outstockProductEntityList)){
                        for(OutstockProductEntity outstockProductEntity:outstockProductEntityList){
                            if(refProductIdNumMap.containsKey(outstockProductEntity.getId())){
                                outstockProductEntity.setInstockNum(Arith.sub(outstockProductEntity.getInstockNum(),
                                        refProductIdNumMap.get(outstockProductEntity.getId())));
                                JSONObject jsonObject = outstockProductEntity.getData();
                                try {
                                    Long refId = jsonObject.getLong(InstockEnum.REF_ID.getAttr());
                                    if(!Objects.isNull(refId)){
                                        refIds.add(refId);
                                    }
                                } catch (Exception e) {
                                    LOG.error("JSON解析异常:" + JSON.toJSONString(outstockProductEntity), e);
                                }
                            }
                        }
                        //更新已入库数量
                        outstockProductModel.updateBatch(outstockProductEntityList, corpid);
                    }
                    //修改 生产单是否有（能）退料入库
                    //查其它的退料入库单
                    Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    params.put("corpid", corpid);
                    params.put("idIn", refIds);
                    params.put("del", DelEnum.NORMAL.getDel());
                    List<InstockEntityExt> instockEntityExts = instockModel.findEntitys(params);
                    Map<Long, List<Long>> refIdInstockIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for(InstockEntityExt instockEntityExt : instockEntityExts){
                        JSONObject jsonObject = instockEntityExt.getData();
                        Long refId = jsonObject.getLong(InstockEnum.REF_ID.getAttr());
                        List<Long> instockIds = refIdInstockIdMap.get(refId);
                        if(CollectionUtils.isEmpty(instockIds)){
                            instockIds = new ArrayList<>();
                            instockIds.add(instockEntityExt.getId());
                            refIdInstockIdMap.put(refId,instockIds);
                        } else {
                            instockIds.add(instockEntityExt.getId());
                            refIdInstockIdMap.put(refId,instockIds);
                        }
                    }
                    if(!refIdInstockIdMap.isEmpty()){
                        Iterator<Map.Entry<Long,List<Long>>> iterator = refIdInstockIdMap.entrySet().iterator();
                        Map<Long, List<InstockProductEntity>> refIdInstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        while (iterator.hasNext()) {
                            Map.Entry<Long, List<Long>> next = iterator.next();
                            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            param.put("corpid", corpid);
                            param.put("instockIdIn", next.getValue());
                            param.put("del", DelEnum.NORMAL.getDel());
                            List<InstockProductEntity> entitys = instockProductModel.findEntitys(param);
                            refIdInstockProductMap.put(next.getKey(),entitys);
                        }
                        List<Long> hasReturnedMaterielIds = new ArrayList<>();
                        Iterator<Map.Entry<Long,List<InstockProductEntity>>> entryIterator = refIdInstockProductMap.entrySet().iterator();
                        while (entryIterator.hasNext()) {
                            Map.Entry<Long, List<InstockProductEntity>> next = entryIterator.next();
                            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            param.put("corpid", corpid);
                            param.put("idIn", next.getValue());
                            param.put("del", DelEnum.NORMAL.getDel());
                            List<InstockProductEntity> entitys = instockProductModel.findEntitys(param);
                            List<Long> outstockProductIds = new ArrayList<>();
                            entitys.forEach(item->{
                                outstockProductIds.add(item.getRefProductId());
                            });
                            Map<String, Object> outstockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            outstockProductParam.put("corpid", corpid);
                            outstockProductParam.put("del", 0);
                            outstockProductParam.put("idIn", outstockProductIds);
                            List<OutstockProductEntityExt> entityList = outstockProductModel.findEntitys(outstockProductParam);
                            for(InstockProductEntity instockProductEntity:entitys){
                                for(OutstockProductEntityExt outstockProductEntity:entityList){
                                    if(Objects.equals(instockProductEntity.getRefProductId(),outstockProductEntity.getId())&&
                                            outstockProductEntity.getProductNum()>instockProductEntity.getProductNum()){
                                        hasReturnedMaterielIds.add(next.getKey());
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                        if(!CollectionUtils.isEmpty(hasReturnedMaterielIds)){
                            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            param.put("corpid", corpid);
                            param.put("idIn", hasReturnedMaterielIds);
                            param.put("del", DelEnum.NORMAL.getDel());
                            List<ProductionOrderEntityExt> productionOrderEntityExts = productionOrderModel.findEntitys(param);
                            List<UpdateDataEntity> updateList = new ArrayList<>();
                            productionOrderEntityExts.forEach(item->{
                                UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                                JSONObject data = item.getData();
                                data.put(ProductionOrderEnum.HAS_RETURNED_MATERIEL.getAttr(), 0);
                                updateDataEntity.setId(item.getId());
                                updateDataEntity.setData((List<UpdateDataValueEntity>) data);
                                updateList.add(updateDataEntity);
                            });
                            productionOrderModel.updateBatch(updateList,corpid);
                        }
                    }
                }
            }
            List<Long> outstockIdIn = retMaterielListDTO.getOutstockIdIn();
            //删除时跟新领料单已领料字段
            if(Objects.equals(businessType, OutstockTypeEnum.MATERIEL_OUTSTOCK.getStockBusinessType()) && !outstockIdIn.isEmpty()) {
                HashSet<Long> refIds = new HashSet<>();
                for (Long id : outstockIdIn) {
                    refIds.add(id);
                }
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("del", 0);
                param.put("corpid", retMaterielListDTO.getCorpid());
                param.put("proOrderIdIn", refIds);
                param.put("type", 2);
                List<ProductionOrderProductEntity> entitys = productionOrderProductModel.findEntitys(param);
                List<OutstockProductEntity> productionOrderProductList = retMaterielListDTO.getProductionOrderProductList();
                Map<Object, Double> outstockNumMap = new HashMap<>();
                List<ProductionOrderProductEntity> updateList = new ArrayList<>();
                for (OutstockProductEntity entity : productionOrderProductList) {
                    if (Objects.nonNull(entity.getRefProductId())) {
                        Double num = outstockNumMap.getOrDefault(entity.getRefProductId(),0D);
                        num += entity.getProductNum();
                        outstockNumMap.put(entity.getRefProductId(), num);
                    }
                }

                for (ProductionOrderProductEntity entity : entitys) {
                    if (outstockNumMap.containsKey(entity.getId())) {
                        entity.setOutstockNum(outstockNumMap.get(entity.getId()) * (-1));
                        entity.setUpdateTime(DateTimeUtil.getInt());
                        updateList.add(entity);
                    }
                }
                if (!updateList.isEmpty()) {
                    productionOrderProductModel.updateOutstockBatch(updateList, corpid);
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("ProductionOrderServiceImpl.updateReturnedMaterielInstock 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 关联新建格式化解释
     *
     * @param handlerExplainInLinkItemDTO 入参
     * @throws XbbException 异常
     */
    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        Integer linkBusinessType = handlerExplainInLinkItemDTO.getLinkBusinessType();
        PaasFormExplainEntity paasFormExplainEntity = handlerExplainInLinkItemDTO.getPaasFormExplainEntity();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        FieldAttrEntity finishProductField = new FieldAttrEntity();
        FieldAttrEntity materielField = new FieldAttrEntity();
        FieldAttrEntity linkBomField = new FieldAttrEntity();
        FieldAttrEntity versionField = new FieldAttrEntity();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (Objects.equals(fieldAttrEntity.getAttr(), ProductionOrderEnum.PRODUCT.getAttr())) {
                finishProductField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), ProductionOrderEnum.MATERIEL.getAttr())) {
                materielField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), ProductionOrderEnum.BOM_ID.getAttr())) {
                linkBomField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), ProductionOrderEnum.BOM_VERSION.getAttr())) {
                versionField = fieldAttrEntity;
            }
        }
        List<OneKeyProduceProductPojo> linkList = handlerExplainInLinkItemDTO.getProductList();

        JSONArray finishedProductArray = new JSONArray();
        Long productId = 0L;
        Double productNum = 0D;
        String unit = null;
        Double rate = 1D;
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(linkBusinessType);
        switch (redundantTemplateTypeEnum) {
            case CONTRACT:
                if(Objects.equals(linkList.size(), 0)){
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205007);
                }
                OneKeyProduceProductPojo oneKeyProduceProductPojo = linkList.get(BasicConstant.ZERO);
                if (Objects.equals(handlerExplainInLinkItemDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())){
                    oneKeyProduceProductPojo.setProductId(oneKeyProduceProductPojo.getId());
                }
                productId = oneKeyProduceProductPojo.getProductId();
                productNum = oneKeyProduceProductPojo.getNum();
                rate = oneKeyProduceProductPojo.getRate() == null ? 1D : oneKeyProduceProductPojo.getRate();
                unit = oneKeyProduceProductPojo.getUnit();
                break;
            case PRODUCT:
                List<Long> idList = new ArrayList<>();
                idList.add(-1L);
                List<ContractProductEntity> productContractEntityList;
                if(!linkList.isEmpty()){
                    linkList.forEach(link -> idList.add(link.getId()));
                    productContractEntityList = contractProductModel.getContractProductByContractIdIn(corpid, 1, idList);
                } else {
                    idList.add(linkDataId);
                    productContractEntityList = contractProductModel.getContractProductByProductIdIn(corpid, 1, idList);
                }
                ContractProductEntity productContractEntity = productContractEntityList.get(BasicConstant.ZERO);
                productId = productContractEntity.getProductId();
                for (ContractProductEntity contractProductEntity : productContractEntityList) {
                    productNum += contractProductEntity.getSumNum();
                }
                productNum = productNum - productContractEntity.getTotal();
                break;
            default:
                throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
        }
        List<ConditionsEntityExt > conditions = new ArrayList<>();
        conditions.add(EsUtil.packageContions(BomBillEnum.STATUS.getAttr(), Collections.singletonList(BasicConstant.ONE), ConditionEnum.EQUAL, BomBillEnum.STATUS.getFieldType()));
        conditions.add(EsUtil.packageContions(BomBillEnum.PRODUCT.getAttr(), Collections.singletonList(productId), ConditionEnum.IN, BomBillEnum.PRODUCT.getFieldType()));
        PaasFormDataEsListVO esListOnlyByCondition = saasDetailTabService.getEsListOnlyByCondition(corpid, XbbRefTypeEnum.BOM_BILL.getCode(), conditions);
        if (Objects.isNull(esListOnlyByCondition) || Objects.isNull(esListOnlyByCondition.getPaasFormDataESList()) || esListOnlyByCondition.getPaasFormDataESList().isEmpty()) {
            throw new XbbException(BomErrorCodeEnum.API_ERROR_242033);
        }
        List<PaasFormDataEntityExt> paasFormDataESList = esListOnlyByCondition.getPaasFormDataESList();
        Long bomId = 0L;
        PaasFormDataEntityExt defaultBomEntity = null;
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            Integer isDefault = getIntegerOrDefaultFromFormData(paasFormDataEntityExt.getData(), BomBillEnum.VERSION_LINK_TEXT.getAttr(), BasicConstant.ZERO);
            if (Objects.equals(isDefault, BasicConstant.IS_DEFAULT)) {
                bomId = paasFormDataEntityExt.getId();
                defaultBomEntity = paasFormDataEntityExt;
                break;
            }
        }
        if (Objects.isNull(defaultBomEntity)) {
            bomId = paasFormDataESList.get(BasicConstant.ZERO).getId();
            defaultBomEntity = paasFormDataESList.get(BasicConstant.ZERO);
        }
        linkBomField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(bomId, defaultBomEntity.getSerialNo()));
        versionField.setDefaultAttr(saasUpdateHelp.setDefaultValue(FastJsonHelper.getStringOrDefaultFromFormData(defaultBomEntity.getData(), BomBillEnum.VERSION.getAttr(), "")));
//        JSONObject finishProduct = new JSONObject();
//        finishProduct.put(StringConstant.PRODUCT_ID, productId);
//        finishProduct.put(StringConstant.NUM, productNum);
//        finishedProductArray.add(finishProduct);
//        BusinessProductListDTO businessProductListDTO = new BusinessProductListDTO();
//        BeanUtil.copyProperties(handlerExplainInLinkItemDTO, businessProductListDTO);
//        BeanUtil.copyProperties(paasFormExplainEntity, businessProductListDTO);
//        businessProductListDTO.setBusinessType(XbbRefTypeEnum.BOM_BILL.getCode());
//        businessProductListDTO.setSourceBusinessType(XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
//        businessProductListDTO.setDataId(bomId);
//        businessProductListDTO.setUserId(handlerExplainInLinkItemDTO.getUserId());
//        businessProductListDTO.setFinishedProductArray(finishedProductArray);
//        BusinessProductListVO businessProductListVO = businessProductService.getBusinessProductList(businessProductListDTO);
//        JSONObject finishedProduct = businessProductListVO.getFinishedProduct();
//        JSONObject materiel = businessProductListVO.getMateriel();
        JSONObject productData= new JSONObject();
        bomBillService.formatProduct4Show2(bomId,corpid,productData, UpdateDataTypeEnum.LINK_ADD);
        if (!linkList.isEmpty() || Objects.equals(linkBusinessType, XbbRefTypeEnum.PRODUCT.getCode())) {
            HashMap<Long,Double> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            linkList.forEach(item -> productMap.put(Objects.equals(RedundantTemplateTypeEnum.CONTRACT, redundantTemplateTypeEnum) ? item.getProductId() : item.getId(),item.getNum()));
            JSONArray productArray = productData.getJSONArray(BomBillEnum.PRODUCT.getAttr());
            //BOM单只会有一个产品
            JSONObject jsonObject = (JSONObject) productArray.get(0);
            Double num = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            //前端传的成品产品数量
            Double frontNum = productMap.getOrDefault(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()),1D);
            if (Objects.equals(linkBusinessType, XbbRefTypeEnum.PRODUCT.getCode())) {
                frontNum = productNum;
            }
            jsonObject.put(SelectProductEnum.NUM.getAttr(),frontNum);
            if (StringUtil.isNotEmpty(unit)) {
                jsonObject.put(SelectProductEnum.UNIT.getAttr(), formDataValidateProductHelp.formatUnit(corpid, unit));
            }
            double div = Arith.div(Arith.mul(rate, frontNum), num);
            JSONArray materialProductArray = productData.getJSONArray(BomBillEnum.MATERIEL.getAttr());
            for (int i = 0; i < materialProductArray.size(); i++) {
                JSONObject json = (JSONObject) materialProductArray.get(i);
                double lossRate = json.getDouble(SelectProductEnum.LOSS_RATE.getAttr()) == null ? 100D : json.getDouble(SelectProductEnum.LOSS_RATE.getAttr());
                lossRate = Arith.sub(1D, Arith.div(lossRate, 100D));
                lossRate = lossRate == 0D ? 1D : lossRate;
                Double materialNum = json.getDouble(SelectProductEnum.NUM.getAttr());
                double mulNum = Arith.div(Arith.mul(materialNum, div), lossRate);
                json.put(SelectProductEnum.NUM.getAttr(),mulNum);
            }
        }
        JSONArray finishedProduct = formDataValidateProductHelp.otherProductToAnother(productData,finishProductField,WorkOrderEnum.SPARE_PARTS.getAttr(),BomBillEnum.PRODUCT.getAttr(),corpid, handlerExplainInLinkItemDTO.getLoginUser(), handlerExplainInLinkItemDTO.getBusinessType(), handlerExplainInLinkItemDTO.getLinkBusinessType());
        JSONArray materiel = formDataValidateProductHelp.otherProductToAnother(productData,materielField,WorkOrderEnum.SPARE_PARTS.getAttr(),BomBillEnum.MATERIEL.getAttr(),corpid, handlerExplainInLinkItemDTO.getLoginUser(), handlerExplainInLinkItemDTO.getBusinessType(), handlerExplainInLinkItemDTO.getLinkBusinessType());
        // 关联产品联动
        // 源单解释
        Map<String, FieldAttrEntity> sourceExplainMap = null;
        // 当前表单解释
        Map<String, FieldAttrEntity> thisExplainMap = null;
        // 当前表单某个关联产品解释
        Map<String, FieldAttrEntity> subThisExplainMap = null;
        // 源单某个关联产品解释
        Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 当前表单某个关联产品子字段与源单某个关联产品对应关系
        Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        LinkProductRelyEntity linkProductRelyEntity;
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(handlerExplainInLinkItemDTO, userAndDepartmentGetDTO);
        UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
        Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
        // 成品产品
        DefaultAttrPoJo defaultAttr = finishProductField.getDefaultAttr();
        String defaultType = defaultAttr.getDefaultType();
        linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, ProductionOrderEnum.PRODUCT.getAttr(), handlerExplainInLinkItemDTO.getFormId(), XbbRefTypeEnum.BOM_BILL.getCode(), DelEnum.NORMAL.getDel());
        if (Objects.nonNull(defaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(defaultType) && Objects.nonNull(linkProductRelyEntity)) {
            // 源表单解释
            PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity> sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
            // 当前表单解释
            PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
            thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(ProductionOrderEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            for (Object o : productData.getJSONArray(BomBillEnum.PRODUCT.getAttr())) {
                JSONObject bomProductData = (JSONObject) o;
                if (!thisToTarget.isEmpty()) {
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    parseSingleRowDataDTO.setDataJsonObject(bomProductData);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if (Objects.isNull(parseSingleRowDataVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                    for (int i = 0; i < finishedProduct.size(); i++) {
                        JSONObject jsonObject = finishedProduct.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID), bomProductData.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID))) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }
            }
        }

        // 物料产品
        DefaultAttrPoJo materielDefaultAttr = materielField.getDefaultAttr();
        String materielDefaultType = materielDefaultAttr.getDefaultType();
        linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, ProductionOrderEnum.MATERIEL.getAttr(), handlerExplainInLinkItemDTO.getFormId(), XbbRefTypeEnum.BOM_BILL.getCode(), DelEnum.NORMAL.getDel());
        if (Objects.nonNull(materielDefaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(materielDefaultType) && Objects.nonNull(linkProductRelyEntity)) {
            //源表单解释
            PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity> sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
            // 当前表单解释
            PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
            thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(ProductionOrderEnum.MATERIEL.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            for (Object o : productData.getJSONArray(BomBillEnum.MATERIEL.getAttr())) {
                JSONObject bomProductData = (JSONObject) o;
                if (!thisToTarget.isEmpty()) {
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    parseSingleRowDataDTO.setDataJsonObject(bomProductData);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if (Objects.isNull(parseSingleRowDataVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                    for (int i = 0; i < materiel.size(); i++) {
                        JSONObject jsonObject = materiel.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID), bomProductData.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID))) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }
            }
        }
        JSONArray productArray = productData.getJSONArray(BomBillEnum.MATERIEL.getAttr());
        List<Long> productIdList = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++){
            JSONObject jsonObject = productArray.getJSONObject(i);
            productIdList.add(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()));
        }
        //分仓库存和成本
        Map<Long,Map<String,JSONObject>> productStockMap = formDataValidateProductHelp.getWarehouseMap(productIdList,corpid);
        JSONObject finishedProductObj = (JSONObject) finishedProduct.get(0);
        Double finishedNum = finishedProductObj.getDouble(SelectProductEnum.NUM.getAttr());
        for (int i = 0;i < materiel.size();i++){
            JSONObject jsonObject = materiel.getJSONObject(i);
            Double materialNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            jsonObject.put("unitNum",Arith.div(materialNum, Arith.mul(rate, finishedNum)));
            JSONObject sourceData = new JSONObject();
            JSONObject productJson = jsonObject.getJSONObject(ProductionOrderMaterielProductEnum.PRODUCT.getAttr());
            sourceData.put("warehouse",productStockMap.getOrDefault(productJson.getLong("id"),new HashMap<>()));
            productJson.put("sourceData",sourceData);
        }
        finishProductField.setDefaultAttr(saasUpdateHelp.setDefaultValue(finishedProduct));
        finishProductField.getDefaultAttr().setDefaultType(defaultType);
        materielField.setDefaultAttr(saasUpdateHelp.setDefaultValue(materiel));
        materielField.getDefaultAttr().setDefaultType(materielDefaultType);
    }

    @Override
    public void batchEditAttr(ProductionOrderEditAttrUpdateDTO productionOrderEditAttrUpdateDTO) throws XbbException {
        try {
            List<ProductionOrderUpdateDTO> paymentList = new ArrayList<>();
            productionOrderEditAttrUpdateDTO.getDataIdList().forEach((item) -> {
                ProductionOrderUpdateDTO payment = new ProductionOrderUpdateDTO();
                payment.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(productionOrderEditAttrUpdateDTO.getFieldEditedList());
                payment.setData(data);
                paymentList.add(payment);
            });
            List<ProductionOrderEntityExt> productionOrderEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!paymentList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", productionOrderEditAttrUpdateDTO.getCorpid());
                param.put("idIn", productionOrderEditAttrUpdateDTO.getDataIdList());
                productionOrderEntityList = productionOrderModel.findEntitys(param);
                if (Objects.isNull(productionOrderEntityList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                //权限团队校验前置了
                List<Long> errorIdList = new ArrayList<>();
//                List<Long> errorIdList = userTeamHelp.batchTeamMembersCheckEditPermission(productionOrderEditAttrUpdateDTO.getBusinessType(), productionOrderEditAttrUpdateDTO.getSaasMark(),
//                        productionOrderEditAttrUpdateDTO.getMenuId(), productionOrderEditAttrUpdateDTO.getLoginUser(), productionOrderEditAttrUpdateDTO.getDistributorMark(),
//                        productionOrderEditAttrUpdateDTO.getDataIdList(), new HashMap<>());
                List<String> errorNameList = new ArrayList<>();
                for (ProductionOrderEntityExt productionOrderEntityExt : productionOrderEntityList) {
                    if (errorIdList.contains(productionOrderEntityExt.getId())) {
                        errorNameList.add(productionOrderEntityExt.getData().getString(ProductionOrderEnum.SHEET_NO.getAttr()));
                    }
                }
                String nameStr = org.apache.commons.lang.StringUtils.join(errorNameList, "、");
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(errorNameList)) {
                    throw new XbbException(UserTeamErrorCodeEnum.API_ERROR_271038.getCode(), String.format(UserTeamErrorCodeEnum.API_ERROR_271038.getMsg(), nameStr));
                }
                ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO = new ProductionOrderUpdateBatchDTO();
                BeanUtil.copyProperties(productionOrderEditAttrUpdateDTO, productionOrderUpdateBatchDTO);
                productionOrderUpdateBatchDTO.setProductionOrderList(paymentList);
                updateBatch(productionOrderUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ProductionOrderEntityExt item : productionOrderEntityList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = productionOrderEditAttrUpdateDTO.getUserId();
            String corpid = productionOrderEditAttrUpdateDTO.getCorpid();
            String loginUserName = productionOrderEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = productionOrderEditAttrUpdateDTO.getFieldType();
            Boolean isFieldDependence = productionOrderEditAttrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence,productionOrderEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(productionOrderEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.PRODUCTION_ORDER.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.PRODUCTION_ORDER.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PRODUCTION_ORDER, OperateTypeEnum.EDIT,
                        "", "", memo, productionOrderEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.PRODUCTION_ORDER.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PRODUCTION_ORDER, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, productionOrderEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productionOrderService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public FormDataAddGetVO produce(ProductionOrderAddGetDTO productionOrderAddGetDTO) throws XbbException {
        FormDataAddGetVO formDataAddGetVO;
        try {
            Long dataId = productionOrderAddGetDTO.getDataId();
            Integer businessType = productionOrderAddGetDTO.getBusinessType();
            Integer linkBusinessType = productionOrderAddGetDTO.getLinkBusinessType();
            String corpid = productionOrderAddGetDTO.getCorpid();
            // 获取解释
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(linkBusinessType, corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            FormDataAddGetDTO formDataAddGetDTO = new FormDataAddGetDTO();
            BeanUtil.copyProperties(productionOrderAddGetDTO, formDataAddGetDTO);
            formDataAddGetDTO.setSubBusinessType(productionOrderAddGetDTO.getSubBusinessType());
            BeanUtil.copyProperties(paasFormExplainEntity, formDataAddGetDTO);
            formDataAddGetVO = paasFormDataService.addGet(formDataAddGetDTO);
            List<FieldAttrEntity> explainList = formDataAddGetVO.getExplainList();
            // 用于存放当前启用的产品模板解释的map
            Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, FieldAttrEntity> nowStockProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            explainHelp.getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, nowStockProductExplainMap);

            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            switch (xbbRefTypeEnum) {
                case SIMULATED_PRODUCTION:
                    BomBillEntityExt bomBillEntityExt = bomBillModel.getByKey(dataId, corpid);
                    if (Objects.isNull(bomBillEntityExt)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
                    }
                    JSONObject bomData = bomBillEntityExt.getData();
                    MaterielDTO materielDTO = productionOrderAddGetDTO.getMateriel().get(0);
                    Long warehouseId = materielDTO.getWarehouse().getId();
                    List<MaterielDTO> materielDTOS = productionOrderAddGetDTO.getMateriel();
                    WarehouseEntityExt warehouseEntity = warehouseModel.getByKey(warehouseId, corpid);
                    if (Objects.isNull(warehouseEntity)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
                    }
                    String warehouseName = FastJsonHelper.getStringOrDefaultFromFormData(warehouseEntity.getData(), WarehouseEnum.WAREHOUSE_NAME.getAttr(), "");
                    FieldAttrEntity finishProductField = new FieldAttrEntity();
                    FieldAttrEntity materielField = new FieldAttrEntity();
                    for(FieldAttrEntity item: explainList) {
                        if (ProductionOrderEnum.BOM_VERSION.getAttr().equals(item.getAttr())) {
                            // bom版本号的默认值
                            item.setDefaultAttr(saasUpdateHelp.setDefaultValue(FastJsonHelper.getStringOrDefaultFromFormData(bomData, BomBillEnum.VERSION.getAttr(), "")));
                        } else if (ProductionOrderEnum.BOM_ID.getAttr().equals(item.getAttr())) {
                            // bom id 的默认值
                            item.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(dataId, bomBillEntityExt.getSerialNo()));
                        } else if (ProductionOrderEnum.PRODUCT_NO.getAttr().equals(item.getAttr())) {
                            item.setDefaultAttr(saasUpdateHelp.setDefaultValue(FastJsonHelper.getStringOrDefaultFromFormData(bomData, BomBillEnum.VERSION.getAttr(), "")));
                        } else if (ProductionOrderEnum.PRODUCT.getAttr().equals(item.getAttr())) {
                            // 成品的默认值
                            finishProductField = item;
                        } else if (ProductionOrderEnum.MATERIEL.getAttr().equals(item.getAttr())) {
                            // 物料产品的默认值
                            materielField = item;
                        } else if (ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr().equals(item.getAttr())) {
                            item.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(warehouseId, warehouseName));
                        }
                    }
                    Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                    param.put(StringConstant.CORPID, corpid);
                    param.put("type", 1);
                    param.put("bomId", dataId);
                    List<BomProductEntity> bomProductList = bomProductModel.findEntitys(param);
                    BomProductEntity bomProductEntity = new BomProductEntity();
                    if (Objects.nonNull(bomProductList)) {
                        bomProductEntity = bomProductList.get(0);
                    }
                    // 数据校验、赋值
                    Long productId = bomProductEntity.getProductId();
                    ProductEntityExt productEntity = productModel.getByKey(productId, corpid);
                    if (productEntity == null) {
                        // 产品不存在
                        throw new XbbException(BomErrorCodeEnum.API_ERROR_242021);
                    }
                    if (productEntity.getDel() == 1) {
                        // 产品已删除
                        throw new XbbException(BomErrorCodeEnum.API_ERROR_242022);
                    }
                    ProductionOrderProductEntityExt productionOrderProductEntityExt = new ProductionOrderProductEntityExt();
                    productionOrderProductEntityExt.setProductId(productId);
                    productionOrderProductEntityExt.setProductNum(productionOrderAddGetDTO.getCanNum());
                    productionOrderProductEntityExt.setProductName(bomProductEntity.getProductName());
                    productionOrderProductEntityExt.setProductNo(bomProductEntity.getProductNo());
                    String specification = bomProductEntity.getProductSpecification();
                    productionOrderProductEntityExt.setProductSpecification(specificationModel.joinSpecification(specification));
                    productionOrderProductEntityExt.setBarcode(FastJsonHelper.getStringOrDefaultFromFormData(productEntity.getData(), ProductEnum.BARCODE.getAttr(), ""));
                    productionOrderProductEntityExt.setProductUnitNum(1D);
                    productionOrderProductEntityExt.setProductUnit(FastJsonHelper.getStringOrDefaultFromFormData(productEntity.getData(), ProductEnum.UNIT.getAttr(), ""));
                    productionOrderProductEntityExt.setImageUrl(FastJsonHelper.getStringOrDefaultFromFormData(productEntity.getData(), ProductEnum.THUMBNAIL.getAttr(), ""));
                    // 物料产品库存，显示仓库产品库存
                    Double stock = getStock(warehouseId, productEntity, Arrays.asList(productId), corpid);
                    productionOrderProductEntityExt.setStock(stock);
                    FormatProductionOrderProductDTO formatProductionOrderProductDTO = new FormatProductionOrderProductDTO();
                    BeanUtil.copyProperties(productionOrderAddGetDTO, formatProductionOrderProductDTO);
                    formatProductionOrderProductDTO.setNowProductExplainMap(nowProductExplainMap);
                    formatProductionOrderProductDTO.setProductionOrderProductEntityExt(productionOrderProductEntityExt);

                    JSONObject productData= new JSONObject();
                    bomBillService.formatProduct4Show2(productionOrderAddGetDTO.getDataId(),corpid,productData, UpdateDataTypeEnum.LINK_ADD);
                    JSONArray finishedProduct = formDataValidateProductHelp.otherProductToAnother(productData,finishProductField,WorkOrderEnum.SPARE_PARTS.getAttr(),BomBillEnum.PRODUCT.getAttr(),corpid, productionOrderAddGetDTO.getLoginUser(), XbbRefTypeEnum.PRODUCTION_ORDER.getCode(), XbbRefTypeEnum.BOM_BILL.getCode());
                    JSONArray materiel = formDataValidateProductHelp.otherProductToAnother(productData,materielField,WorkOrderEnum.SPARE_PARTS.getAttr(),BomBillEnum.MATERIEL.getAttr(),corpid, productionOrderAddGetDTO.getLoginUser(), XbbRefTypeEnum.PRODUCTION_ORDER.getCode(), XbbRefTypeEnum.BOM_BILL.getCode());
                    // 关联产品联动
                    // 源单解释
                    Map<String, FieldAttrEntity> sourceExplainMap = null;
                    // 当前表单解释
                    Map<String, FieldAttrEntity> thisExplainMap = null;
                    // 当前表单某个关联产品解释
                    Map<String, FieldAttrEntity> subThisExplainMap = null;
                    // 源单某个关联产品解释
                    Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    // 当前表单某个关联产品子字段与源单某个关联产品对应关系
                    Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
                    BeanUtil.copyProperties(productionOrderAddGetDTO, userAndDepartmentGetDTO);
                    UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
                    Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
                    Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
                    // 成品产品
                    DefaultAttrPoJo defaultAttr = finishProductField.getDefaultAttr();
                    String defaultType = defaultAttr.getDefaultType();
                    LinkProductRelyEntity linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndLinkFormId(corpid, ProductionOrderEnum.PRODUCT.getAttr(), formDataAddGetVO.getPaasFormEntity().getId(), bomBillEntityExt.getFormId(), DelEnum.NORMAL.getDel());
                    if (Objects.nonNull(defaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(defaultType) && Objects.nonNull(linkProductRelyEntity)) {
                        // 源表单解释
                        PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
                        List<FieldAttrEntity> sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                        sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
                        // 当前表单解释
                        PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
                        thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
                        subThisExplainMap = businessProductService.getProductRelyMap(ProductionOrderEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
                        for (Object o : productData.getJSONArray(BomBillEnum.PRODUCT.getAttr())) {
                            JSONObject bomProductData = (JSONObject) o;
                            if (!thisToTarget.isEmpty()) {
                                ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                                parseSingleRowDataDTO.setDataJsonObject(bomProductData);
                                parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                                parseSingleRowDataDTO.setUserMap(userMap);
                                parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                                ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                                if (Objects.isNull(parseSingleRowDataVO)) {
                                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                                }
                                JSONObject result = parseSingleRowDataVO.getResult();
                                JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                                for (int i = 0; i < finishedProduct.size(); i++) {
                                    JSONObject jsonObject = finishedProduct.getJSONObject(i);
                                    if (Objects.equals(jsonObject.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID), bomProductData.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID))) {
                                        jsonObject.putAll(thisData);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    // 物料产品
                    DefaultAttrPoJo materielDefaultAttr = materielField.getDefaultAttr();
                    String materielDefaultType = materielDefaultAttr.getDefaultType();
                    linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndLinkFormId(corpid, ProductionOrderEnum.MATERIEL.getAttr(), formDataAddGetVO.getPaasFormEntity().getId(), bomBillEntityExt.getFormId(), DelEnum.NORMAL.getDel());
                    if (Objects.nonNull(materielDefaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(materielDefaultType) && Objects.nonNull(linkProductRelyEntity)) {
                        //源表单解释
                        PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
                        List<FieldAttrEntity> sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                        sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
                        // 当前表单解释
                        PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
                        thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
                        subThisExplainMap = businessProductService.getProductRelyMap(ProductionOrderEnum.MATERIEL.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
                        for (Object o : productData.getJSONArray(BomBillEnum.MATERIEL.getAttr())) {
                            JSONObject bomProductData = (JSONObject) o;
                            if (!thisToTarget.isEmpty()) {
                                ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                                parseSingleRowDataDTO.setDataJsonObject(bomProductData);
                                parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                                parseSingleRowDataDTO.setUserMap(userMap);
                                parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                                ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                                if (Objects.isNull(parseSingleRowDataVO)) {
                                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                                }
                                JSONObject result = parseSingleRowDataVO.getResult();
                                JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                                for (int i = 0; i < materiel.size(); i++) {
                                    JSONObject jsonObject = materiel.getJSONObject(i);
                                    if (Objects.equals(jsonObject.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID), bomProductData.getLongValue(BusinessConstant.RELY_PRODUCT_SUB_ID))) {
                                        jsonObject.putAll(thisData);
                                        break;
                                    }
                                }
                            }
                        }
                    }
//                    JSONObject warehouseObj = new JSONObject();
//                    warehouseObj.put("id",warehouseId);
//                    warehouseObj.put("name",warehouseName);
                    for (int i = 0;i < materiel.size();i++){
                        JSONObject jsonObject = materiel.getJSONObject(i);
                        MaterielDTO materiels = materielDTOS.get(i);
                        JSONObject warehouseObj = new JSONObject();
                        warehouseObj.put("id",materiels.getWarehouse().getId());
                        warehouseObj.put("name",materiels.getWarehouse().getValue());
                        jsonObject.put(SelectProductEnum.WAREHOUSE.getAttr(),Collections.singletonList(warehouseObj));
                        Double unitNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr()) == null ? 1 : jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
                        jsonObject.put("unitNum", jsonObject.getDouble(SelectProductEnum.NUM.getAttr()));
                        Double lossRate = jsonObject.getDouble(SelectProductEnum.LOSS_RATE.getAttr()) == null ? 0D : jsonObject.getDouble(SelectProductEnum.LOSS_RATE.getAttr());
                        Double num = Arith.div(unitNum, Arith.sub(1, Arith.div(lossRate, 100)));
                        jsonObject.put(SelectProductEnum.NUM.getAttr(), num);
                    }
                    finishProductField.setDefaultAttr(saasUpdateHelp.setDefaultValue(finishedProduct));
                    materielField.setDefaultAttr(saasUpdateHelp.setDefaultValue(materiel));
//                    // 成品的默认值
//                    formatProductionOrderProductDTO.setTargetCode(XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
//                    JSONObject productObj = getFormatProductJsonArray(formatProductionOrderProductDTO);
//                    JSONArray productArray = new JSONArray();
//                    productArray.add(productObj);
//                    JSONObject productFinalObj = new JSONObject();
//                    productFinalObj.put(StringConstant.PRODUCT_LIST, productArray);
//                    productFinalObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, ProductionOrderEnum.PRODUCT.getAttr());
//                    productFinalObj.put(BusinessConstant.EXPLAINS, saasUpdateHelp.getSelectProductExplains(XbbRefTypeEnum.BOM_BILL, corpid, BomBillEnum.PRODUCT.getAttr()));
//                    finishProductField.setDefaultAttr(saasUpdateHelp.setDefaultValue(productFinalObj));
//                    // 物料组装数据
//                    JSONObject materielProductFinalObj = new JSONObject();
//                    JSONArray materielProductArray = getMaterielList(productionOrderAddGetDTO, nowProductExplainMap);
//                    // 物料产品
//                    materielProductFinalObj.put(StringConstant.PRODUCT_LIST, materielProductArray);
//                    materielProductFinalObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, ProductionOrderEnum.MATERIEL.getAttr());
//                    materielProductFinalObj.put(BusinessConstant.EXPLAINS, saasUpdateHelp.getSelectProductExplains(XbbRefTypeEnum.BOM_BILL, corpid, BomBillEnum.MATERIEL.getAttr()));
//                    materielField.setDefaultAttr(saasUpdateHelp.setDefaultValue(materielProductFinalObj));
                    break;
                default:
                    break;
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productionOrderService.produce 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return formDataAddGetVO;
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        String corpid = importFormDataDTO.getCorpid();
        JSONObject dataJson = new JSONObject();
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        for (FieldAttrEntityForImport fieldAttr : fieldAttrList) {
            String attr = fieldAttr.getAttr();
            String attrName = fieldAttr.getAttrName();
            Integer fieldType = fieldAttr.getFieldType();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);

            if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())) {
                // 成品产品只能填写一条数据
                List<List<CellValuePojo>> firstRowValueList = new ArrayList<>();
                firstRowValueList.add(cellValueList);
                importHelper.formatCommonProduct(titlePojoList, dataJson, firstRowValueList, fieldAttr, XbbRefTypeEnum.PRODUCTION_ORDER.getCode(), corpid);
            } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())) {
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, fieldAttr, XbbRefTypeEnum.PRODUCTION_ORDER.getCode(), corpid);
            } else if (Objects.equals(attr, ProductionOrderEnum.BOM_ID.getAttr())) {
                importHelper.formatLinkBusinessValue4Import(dataJson, fieldAttr, cellValue);
                // 设置关联BOM版本字段
                Map<String, Object> linkBusinessMap = fieldAttr.getLinkBusinessMap();
                Object linkBusiness = linkBusinessMap.get(Objects.toString(cellValue));
                if (Objects.nonNull(linkBusiness) && linkBusiness instanceof PaasFormDataEntityExt) {
                    PaasFormDataEntityExt bomEntity = (PaasFormDataEntityExt) linkBusiness;
                    String bomVersion = bomEntity.getData().getString(BomBillEnum.VERSION.getAttr());
                    dataJson.put(ProductionOrderEnum.BOM_VERSION.getAttr(), bomVersion);
                }
            } else if (Objects.equals(attr, ProductionOrderEnum.BOM_VERSION.getAttr())) {
                // 关联BOM版本字段在关联BOM清单字段处理时已经设置了
            } else if (Objects.equals(attr, ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr()) || Objects.equals(attr, ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr())) {
                importHelper.formatWareHouse4Import(dataJson, fieldAttr, attr, cellValue);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                formDataAddDTO.setSerialNo(Objects.toString(cellValue, ""));
            } else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttr, dataJson);
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttr.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttr, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                    importHelper.formatLinkData(cellValue, fieldAttr, dataJson);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                    importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttr, dataJson);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        JSONArray bomArray = dataJson.getJSONArray(ProductionOrderEnum.BOM_ID.getAttr());
        if (bomArray == null || bomArray.isEmpty()) {
            throw new XbbException(WarehouseErrorCodeEnum.API_ERROR_244016.getCode(), WarehouseErrorCodeEnum.API_ERROR_244016.getMsg());
        }
        Long bomId = bomArray.getJSONObject(0).getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
        List<BomProductEntity> bomProductList = bomProductModel.getProductsByBomId(bomId, corpid, null);
        Map<Long, Double> lossRateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Double> unitNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (BomProductEntity bomProductEntity : bomProductList) {
            if (Objects.equals(bomProductEntity.getType(), 2)) {
                lossRateMap.put(bomProductEntity.getProductId(), bomProductEntity.getAttritionRate());
                unitNumMap.put(bomProductEntity.getProductId(), bomProductEntity.getProductNum());
            }
        }
        JSONArray materielProductarray = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataJson,ProductionOrderEnum.MATERIEL.getAttr(),new JSONArray());
        for (int i = 0; i < materielProductarray.size(); i++) {
            JSONObject materialJson = materielProductarray.getJSONObject(i);
            Long materialProductId = materialJson.getJSONObject(SelectProductEnum.PRODUCT.getAttr()).getLong(FieldTypeEnum.DATAID.getAlias());
            Double lossRate = materialJson.getDouble(ProductionOrderMaterielProductEnum.LOSS_RATE.getAttr());
            Double unitNum = materialJson.getDouble("unitNum");
            if (Objects.isNull(lossRate) || Objects.equals(lossRate, 0D)) {
                materialJson.put(ProductionOrderMaterielProductEnum.LOSS_RATE.getAttr(), lossRateMap.getOrDefault(materialProductId,0D));
            }
            if (Objects.isNull(unitNum) || Objects.equals(unitNum, 0D)) {
                materialJson.put("unitNum", unitNumMap.getOrDefault(materialProductId,0D));
            }
        }
        return formDataAddDTO;
    }

    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        List<Long> idList = new ArrayList<>();
        paasFormDataESList.forEach(item -> idList.add(item.getDataId()));

        // 关联产品map
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("proOrderIdIn", idList);
        params.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        List<ProductionOrderProductEntity> productionOrderProductList = productionOrderProductModel.findEntitys(params);
        Set<Long> warehouseIdIn = new HashSet<>();
        Set<Long> productIdIn = new HashSet<>();
        Map<Long, List<ProductionOrderProductEntity>> materialProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, ProductionOrderProductEntity> finishProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productionOrderProductList.forEach(item -> {
            warehouseIdIn.add(item.getWarehouseId());
            productIdIn.add(item.getProductId());
            Long refId = item.getProductionOrderId();
            if (Objects.equals(item.getType(), 2)) {
                if (materialProductMap.containsKey(refId)) {
                    materialProductMap.get(refId).add(item);
                } else {
                    List<ProductionOrderProductEntity> productEntityList = new ArrayList<>();
                    productEntityList.add(item);
                    materialProductMap.put(refId, productEntityList);
                }
            } else {
                finishProductMap.put(refId, item);
            }
        });

        // 所有产品map
        params.clear();
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("idIn", productIdIn);
        List<ProductEntityExt> productList = productModel.findEntitys(params);
        Map<Long, ProductEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productIdIn.clear();
        productList.forEach(item -> {
            productMap.put(item.getId(), item);
            productIdIn.add(item.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
        });
        params.clear();
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("idIn", productIdIn);
        List<ProductEntityExt> parentProductList = productModel.findEntitys(params);
        parentProductList.forEach(item -> productMap.put(item.getId(), item));

        // 仓库数据
        params.clear();
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("idIn", warehouseIdIn);
        List<WarehouseEntityExt> warehouseList = warehouseModel.findEntitys(params);
        Map<Long, WarehouseEntityExt> warehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        warehouseList.forEach(item -> warehouseMap.put(item.getId(), item));

        // 成品 物料字段解释
        FieldAttrEntityForImport productFieldAttr = new FieldAttrEntityForImport();
        FieldAttrEntityForImport materialFieldAttr = new FieldAttrEntityForImport();
        for (FieldAttrEntityForImport fieldAttr : fieldAttrList) {
            if (Objects.equals(fieldAttr.getAttr(), ProductionOrderEnum.PRODUCT.getAttr())) {
                productFieldAttr = fieldAttr;
            } else if (Objects.equals(fieldAttr.getAttr(), ProductionOrderEnum.MATERIEL.getAttr())) {
                materialFieldAttr = fieldAttr;
            }
        }
        Map<String, MultiUnitItemPoJo> groupBaseUnitStringMap = relativeProductHelp.getGroupBaseUnitStringMap(formDataListDTO.getCorpid());

        // 暂时只处理产品
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject formDataObj = paasFormDataEntityExt.getData();
            Long dataId = paasFormDataEntityExt.getDataId();

            ProductionOrderProductEntity finishProduct = finishProductMap.get(dataId);
            List<ProductionOrderProductEntity> finishProductEntityList = new ArrayList<>();
            if (Objects.nonNull(finishProduct)) {
                finishProductEntityList.add(finishProduct);
            }
            JSONArray finishProductArray = new JSONArray();
            for (ProductionOrderProductEntity finishProductEntity : finishProductEntityList) {
                Long productId = finishProductEntity.getProductId();
                Double num = finishProductEntity.getProductNum();
                if (Objects.nonNull(finishProductEntity.getPriceData()) && finishProductEntity.getPriceData().size() > BasicConstant.ZERO){
                    finishProductEntity.getData().putAll(finishProductEntity.getPriceData());
                }
                // 产品信息转换
                JSONObject productObj = finishProductEntity.getData() == null ? new JSONObject() : finishProductEntity.getData();
                importHelper.formatProduct4Export(productMap, null, productId, num, null, productObj);
                productObj.put(SelectProductEnum.MEMO.getAttr(), finishProductEntity.getMemo());
                //基本单位时直接塞入productUnit
                if (Objects.isNull(finishProductEntity.getBusinessUnit())){
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                        finishProductEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                    productObj.put(SelectProductEnum.NUM.getAttr(), finishProductEntity.getProductNum());
                }else {
                    productObj.put(ProductEnum.UNIT.getAttr(), finishProductEntity.getBusinessUnit());
                    productObj.put(SelectProductEnum.NUM.getAttr(), finishProductEntity.getBusinessNum());
                }

                if(Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), finishProductEntity.getProductUnit());
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  finishProductEntity.getProductNum());
                }else {
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                }
                finishProductArray.add(productObj);
            }
            formDataObj.put(productFieldAttr.getAttr(), finishProductArray);

            List<ProductionOrderProductEntity> materialProductEntityList = materialProductMap.get(dataId);
            if (Objects.isNull(materialProductEntityList)) {
                materialProductEntityList = new ArrayList<>();
            }
            JSONArray materialProductArray = new JSONArray();
            for (ProductionOrderProductEntity materialProductEntity : materialProductEntityList) {
                if (Objects.isNull(materialProductEntity)) {
                    continue;
                }
                if (Objects.nonNull(materialProductEntity.getPriceData()) && materialProductEntity.getPriceData().size() > BasicConstant.ZERO){
                    materialProductEntity.getData().putAll(materialProductEntity.getPriceData());
                }
                double rate = materialProductEntity.getRate() == null ? 1 : materialProductEntity.getRate();
                Long productId = materialProductEntity.getProductId();
                Double num = materialProductEntity.getProductNum();
                Long warehouseId = materialProductEntity.getWarehouseId();
                Double attritionRate = materialProductEntity.getAttritionRate();
                // 产品信息转换
                JSONObject productObj = materialProductEntity.getData() == null ? new JSONObject() : materialProductEntity.getData();
                importHelper.formatProduct4Export(productMap, warehouseMap, productId, num, warehouseId, productObj);
                productObj.put(ProductionOrderMaterielProductEnum.LOSS_RATE.getAttr(), attritionRate);
                productObj.put(ProductionOrderMaterielProductEnum.MEMO.getAttr(), materialProductEntity.getMemo());
                productObj.put(ProductionOrderMaterielProductEnum.OUTSTOCK_NUM.getAttr(), Arith.div(materialProductEntity.getOutstockNum(), rate));
                productObj.put(ProductionOrderMaterielProductEnum.WAIT_OUTSTOCK_NUM.getAttr(), Arith.sub(materialProductEntity.getProductNum(),materialProductEntity.getOutstockNum()) > 0 ? Arith.div(Arith.sub(materialProductEntity.getProductNum(),materialProductEntity.getOutstockNum()), rate) : 0);
                //基本单位时直接塞入productUnit
                if (Objects.isNull(materialProductEntity.getBusinessUnit())){
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                        materialProductEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                    productObj.put(SelectProductEnum.NUM.getAttr(), materialProductEntity.getProductNum());
                }else {
                    productObj.put(ProductEnum.UNIT.getAttr(), materialProductEntity.getBusinessUnit());
                    productObj.put(SelectProductEnum.NUM.getAttr(), materialProductEntity.getBusinessNum());
                }

                if(Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), materialProductEntity.getProductUnit());
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  materialProductEntity.getProductNum());
                }else {
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                }
                materialProductArray.add(productObj);
            }
            formDataObj.put(materialFieldAttr.getAttr(), materialProductArray);
        }
    }

    @Override
    public BaseVO changeStatus(ChangeStatusDTO changeStatusDTO) throws XbbException {
        // TODO 生产单编辑权限校验
        Long dataId = changeStatusDTO.getDataId();
        Integer businessType = changeStatusDTO.getBusinessType();
        String corpid = changeStatusDTO.getCorpid();
        PaasFormDataEntityExt paasFormDataEntityExt = saasGetHelp.getFormData(dataId, corpid, businessType);
        if (paasFormDataEntityExt == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        JSONObject bomData = paasFormDataEntityExt.getData();
        String status = changeStatusDTO.getType();
        String oldStatus = FastJsonHelper.getStringOrDefaultFromFormData(bomData, ProductionOrderEnum.STATUS.getAttr(), "");
        if (Objects.equals(oldStatus, status)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, ErrorMessageConstant.STATUS_NOT_MODIFIED);
        } else {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(ProductionOrderEnum.STATUS.getAttr(), status);
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
            productionOrderModel.updateBatch(Collections.singletonList(updateData), corpid);
            //  TODO 消息
        }
        return new BaseVO();
    }

    /**
     * 获取物料产品信息
     * @param productionOrderAddGetDTO
     * @param nowProductExplainMap
     * @return 返回物料
     * @throws XbbException
     */
    private JSONArray getMaterielList(ProductionOrderAddGetDTO productionOrderAddGetDTO, Map<String, FieldAttrEntity> nowProductExplainMap) throws XbbException{
        JSONArray materielProductArray = new JSONArray();
        String corpid = productionOrderAddGetDTO.getCorpid();
        List<MaterielDTO> materielDTOList = productionOrderAddGetDTO.getMateriel();
        Long bomId = productionOrderAddGetDTO.getDataId();
        Map<Long, MaterielDTO> materielDTOMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        materielDTOList.forEach(item->{
            materielDTOMap.put(item.getId(), item);
        });
        Double canNum = productionOrderAddGetDTO.getCanNum();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("del", 0);
        params.put("bomId", bomId);
        params.put("type", 2);
        List<BomProductEntity> bomProductEntities = bomProductModel.findEntitys(params);
        if (Objects.nonNull(bomProductEntities) && !bomProductEntities.isEmpty()) {
            List<Long> productIdIn = new ArrayList<>();
            bomProductEntities.forEach(item->{
                productIdIn.add(item.getProductId());
            });
            // 根据productIdIn获取对应产品信息
            Map<Long, ProductEntityExt> productMap = productModel.getProductMapByIdIn(corpid, productIdIn, null);
            for (BomProductEntity item : bomProductEntities) {
                Long materielProductId = item.getProductId();
                MaterielDTO materielObj = materielDTOMap.get(materielProductId);
                if (materielObj == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
                }
                ProductEntityExt productEntityExt = productMap.get(materielProductId);
                if (productEntityExt == null) {
                    // 产品不存在
                    throw new XbbException(BomErrorCodeEnum.API_ERROR_242021);
                }
                if (productEntityExt.getDel() == 1) {
                    // 产品已删除
                    throw new XbbException(BomErrorCodeEnum.API_ERROR_242022);
                }
                // 计算物料产品数量
                Double stock = materielObj.getStock();
                Double unitNum = item.getProductNum();
                Double attritionRate = item.getAttritionRate();
                // 领料数量计算公式 (成品生产数量*物料产品单位数量)/(1-损耗率%)
                Double productNum = Arith.div(Arith.mul(canNum, unitNum), Arith.div(Arith.sub(100, attritionRate), 100));

                if (productNum > stock) {
                    productNum = stock;
                }
                ProductionOrderProductEntityExt entity = new ProductionOrderProductEntityExt();
                // 仓库校验
                WarehouseDTO outWarehouse = materielObj.getWarehouse();
                if (outWarehouse == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
                }
                Long warehouseId = outWarehouse.getId();
                // 给物料产品赋值
                Double productStock = getStock(warehouseId, productEntityExt, Arrays.asList(materielProductId), corpid);
                entity.setStock(productStock);
                entity.setProductName(item.getProductName());
                entity.setProductId(materielProductId);
                entity.setProductNum(productNum);
                entity.setProductNo(item.getProductNo());
                entity.setProductSpecification(item.getProductSpecification());
                entity.setBarcode(FastJsonHelper.getStringOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.BARCODE.getAttr(), ""));
                entity.setProductUnitNum(unitNum);
                entity.setProductUnit(FastJsonHelper.getStringOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.UNIT.getAttr(), ""));
                entity.setAttritionRate(attritionRate);
                entity.setWarehouseId(warehouseId);
                entity.setImageUrl(FastJsonHelper.getStringOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.THUMBNAIL.getAttr(), ""));
                JSONObject warehouse = new JSONObject();
                warehouse.put("id", outWarehouse.getId());
                warehouse.put("value", outWarehouse.getValue());
                entity.setWarehouseObj(warehouse);
                entity.setType(item.getType());
                FormatProductionOrderProductDTO formatProductionOrderProductDTO = new FormatProductionOrderProductDTO();
                BeanUtil.copyProperties(productionOrderAddGetDTO, formatProductionOrderProductDTO);
                formatProductionOrderProductDTO.setNowProductExplainMap(nowProductExplainMap);
                formatProductionOrderProductDTO.setProductionOrderProductEntityExt(entity);
                formatProductionOrderProductDTO.setTargetCode(XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
                JSONObject productObj = getFormatProductJsonArray(formatProductionOrderProductDTO);
                materielProductArray.add(productObj);
            }
        }
        return materielProductArray;
    }

    /**
     * 获取产品库存
     * @param warehouseId
     * @param productEntityExt
     * @param corpid
     * @return
     * @throws XbbException
     */
    private Double getStock(Long warehouseId, ProductEntityExt productEntityExt, List<Long> productIdList, String corpid) throws XbbException {
        Double productStock = 0D;
        try {
            if (productEntityExt == null) {
                throw new XbbException(BomErrorCodeEnum.API_ERROR_242021);
            }
            Long productId = productEntityExt.getId();
            if (warehouseId != null) {
                // 需要查询的字段
                List<String> fieldList = Arrays.asList(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("productId"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("num"));
                // 生产单产品分仓库存
                Map<Long, ProductWarehouseEntity> warehouseMap = productWarehouseModel.getWarehouseProductList(corpid, warehouseId, productIdList, fieldList);
                if (warehouseMap != null && warehouseMap.containsKey(productId)) {
                    productStock = warehouseMap.get(productId).getNum();
                }
            } else {
                productStock = getDoubleOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.STOCK.getAttr(), 0D);
            }
        } catch (Exception e) {
            LOG.error("productionOrderService.produce 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productStock;
    }



    @Override
    public boolean judgeProductionOrderAllOutBound(Long outstockId, Long productionOrderId, String corpid, List<ProductSavePojo> productSavePojoList) throws XbbException {
        return productionOrderHelp.judgeProductionOrderAllOutBound(outstockId, productionOrderId, corpid, productSavePojoList);
    }

    @Override
    public boolean judgeProductionOrderAllInBound(Long instockId, Long productionOrderId, String corpid, List<ProductSavePojo> productSavePojoList) throws XbbException {
        return productionOrderHelp.judgeProductionOrderAllInBound(instockId, productionOrderId, corpid, productSavePojoList);
    }

    @Override
    public void dataConsistencyUpdateWarehouse(String corpid, Long dataId, String name) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0));
            BoolQueryBuilder filter1 = boolQuery()
                    .filter(termQuery(ProductionOrderEnum.getEsAttr4Keyword(ProductionOrderEnum.INTO_WAREHOUSE_ID), dataId));
            BoolQueryBuilder filter2 = boolQuery()
                    .filter(termQuery(ProductionOrderEnum.getEsAttr4Keyword(ProductionOrderEnum.OUT_WAREHOUSE_ID), dataId));
            filter.should(filter1);
            filter.should(filter2);
            filter.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCTION_ORDER, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<ProductionOrderEntityExt> productionOrderEntityExts = productionOrderModel.findEntitys(param);

            if (Objects.nonNull(productionOrderEntityExts) && !productionOrderEntityExts.isEmpty()) {
                List<ProductionOrderUpdateDTO> productionOrderUpdateDTOList = new ArrayList<>();
                for (ProductionOrderEntityExt entityExt : productionOrderEntityExts) {
                    JSONObject data = entityExt.getData();
                    Long inWarehouseId = data.getLong(ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr());
                    Long outWarehouseId = data.getLong(ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr());
                    JSONObject updateData = new JSONObject();
                    if (Objects.equals(inWarehouseId, dataId)) {
                        updateData.put(ProductionOrderEnum.INTO_WAREHOUSE_ID_LINK_TEXT.getAttr(), name);
                    } else if (Objects.equals(outWarehouseId, dataId)) {
                        updateData.put(ProductionOrderEnum.OUT_WAREHOUSE_ID_LINK_TEXT.getAttr(), name);
                    }

                    ProductionOrderUpdateDTO productionOrderUpdateDTO = new ProductionOrderUpdateDTO();
                    productionOrderUpdateDTO.setId(entityExt.getId());
                    productionOrderUpdateDTO.setData(updateData);
                    productionOrderUpdateDTOList.add(productionOrderUpdateDTO);
                }

                ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO = new ProductionOrderUpdateBatchDTO();
                productionOrderUpdateBatchDTO.setCorpid(corpid);
                productionOrderUpdateBatchDTO.setProductionOrderList(productionOrderUpdateDTOList);
                updateBatch(productionOrderUpdateBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("ProductionOrderServiceImpl.dataConsistencyUpdateWarehouse 出错， corpid=" + corpid + "  warehouseId=" + dataId + "  warehouseName=" + name, e);
        }
    }

    @Override
    public ProductSummaryVO summaryProductList(BusinessProductListDTO businessProductListDTO) throws XbbException {
        // 获取参数
        String corpid = businessProductListDTO.getCorpid();
        Long dataId = businessProductListDTO.getDataId();
        String attr = businessProductListDTO.getAttr();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put(ParameterConstant.PRODUCTION_ORDER_ID, dataId);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())) {
            modelMap.put(ParameterConstant.TYPE, 1);
        } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())) {
            modelMap.put(ParameterConstant.TYPE, 2);
        }
        modelMap.put("columns", "product_id,product_num, type,rate");
        List<ProductionOrderProductEntity> productionOrderProductEntities = productionOrderProductModel.findEntitys(modelMap);
        ProductSummaryVO businessProductListVO = new ProductSummaryVO();
        if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())) {
            EsDataDTO esDataDTO = new EsDataDTO();
            esDataDTO.setCorpid(corpid);
            esDataDTO.setDel(0);
            esDataDTO.setBusinessType(XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode());
            esDataDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
            esDataDTO.setFieldList(null);
            esDataDTO.setPageSize(1000);
            List<ConditionsEntityExt> conditionsEntityExtList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            conditionsEntityExtList.add(EsUtil.packageContions(InstockEnum.REF_ID.getAttr(),
                    Collections.singletonList(dataId), ConditionEnum.EQUAL, InstockEnum.REF_ID.getFieldType()));
            conditionsEntityExtList.add(EsUtil.packageContions(InstockEnum.TYPE.getAttr(),
                    Collections.singletonList(InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode()), ConditionEnum.EQUAL, InstockEnum.TYPE.getFieldType()));
            esDataDTO.setConditionsEntityExtList(conditionsEntityExtList);
            PaasFormDataEsListVO esDataList = paasFormDataService.getEsDataList(esDataDTO);
            List<PaasFormDataEntityExt> instockESList = esDataList.getPaasFormDataESList();

            List<Long> instockIdIn = new ArrayList<>();
            instockESList.forEach(instock -> instockIdIn.add(instock.getId()));
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("instockIdIn", instockIdIn);
            List<InstockProductEntity> instockProductEntities = instockProductModel.findEntitys(param);

            List<Long> finishProductIdList = new ArrayList<>();
            // 成品总数量
            double totalFinishProductNum = 0D;
            Double finishRate = 1D;
            for (ProductionOrderProductEntity productionOrderProduct : productionOrderProductEntities) {
                if (Objects.equals(productionOrderProduct.getType(), 1)) {
                    finishRate = productionOrderProduct.getRate() == null ? 1D : productionOrderProduct.getRate();
                    totalFinishProductNum = Arith.add(totalFinishProductNum, Arith.div(productionOrderProduct.getProductNum(), finishRate));
                    finishProductIdList.add(productionOrderProduct.getProductId());
                }
            }
            // 已入库成品数量
            AtomicReference<Double> instockProductNum = new AtomicReference<>(0D);
            instockProductEntities.forEach(instockProduct -> {
                if (finishProductIdList.contains(instockProduct.getProductId())) {
                    instockProductNum.set(Arith.add(instockProductNum.get(), instockProduct.getProductNum()));
                }
            });
            JSONObject others = new JSONObject();
            others.put(BusinessConstant.ALREADY_INSTOCK, Arith.div(instockProductNum.get(), finishRate));
            Double waitInstockNum = Arith.sub(totalFinishProductNum, Arith.div(instockProductNum.get(), finishRate));
            waitInstockNum = waitInstockNum < 0D ? 0D : waitInstockNum;
            others.put(BusinessConstant.DELAY_INSTOCK, waitInstockNum);
            businessProductListVO.setOthers(others);
            businessProductListVO.setBusinessType(businessProductListDTO.getBusinessType());
        }
        Double num = 0D;
        Double materielRate;
        for (ProductionOrderProductEntity productEntity : productionOrderProductEntities) {
            materielRate = productEntity.getRate() == null ? 1D : productEntity.getRate();
            Double productNum = productEntity.getProductNum() != null ? productEntity.getProductNum(): 0D;
            num = Arith.add(num, Arith.div(productNum, materielRate));
        }

        // 24220 【app-生产单】详情页物料产品界面小数位数显示不正确
        BigDecimal bigDecimal = BigDecimal.valueOf(num);
        if (ProductionOrderEnum.MATERIEL.getAttr().equals(attr)) {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains());
            FieldAttrEntity fieldAttrEntity = explainMap.get(ProductEnum.STOCK.getAttr());
            Integer accuracy = fieldAttrEntity.getAccuracy();
            bigDecimal = bigDecimal.setScale(accuracy, BigDecimal.ROUND_HALF_UP);
        }
        Integer productSize = productionOrderProductEntities.size();
        String summaryInfo = String.format(I18nMessageUtil.getMessage(StringConstant.PRODUCTS_TYPE_NUM), productSize, bigDecimal);
        businessProductListVO.setSummaryInfo(summaryInfo);
        return businessProductListVO;
    }

    @Override
    public void updateBatchByBusinessRule(ProductionOrderUpdateByBusinessRuleDTO productionOrderUpdateByBusinessRuleDTO) throws XbbException {
        try {
            String corpid = productionOrderUpdateByBusinessRuleDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = productionOrderUpdateByBusinessRuleDTO.getFormDataList();
            List<UpdateDataEntity> updateList = ExplainUtil.getUpdateValueByBusinessRule(productionOrderUpdateByBusinessRuleDTO.getFormDataList(), corpid, productionOrderUpdateByBusinessRuleDTO.getOperations());

            if (!updateList.isEmpty()) {
                productionOrderModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(productionOrderUpdateByBusinessRuleDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        } catch (Exception e) {
            LOG.error("productionOrderService.updateFormDataByBusinessRule根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }
}
